motiejus/zig

fork of https://codeberg.org/ziglang/zig
git clone https://git.jakstys.lt/motiejus/zig.git
Log | Tree | Refs | README | LICENSE

commit d7b6d637df5b94ec07cf017fa742e8c34a4b9433 (tree)
parent 3c16e8037261e2f19e4a4daf9c88453ec11281b3
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 19 Jan 2024 12:14:30 -0800

Merge pull request #18615 from ziglang/langref

miscellaneous documentation changes
Diffstat:
Mdoc/langref.html.in | 296+++++++------------------------------------------------------------------------
Mlib/std/Build.zig | 10++++++++++
Mlib/std/Build/Module.zig | 3+++
Mlib/std/Build/Step/Options.zig | 2++
4 files changed, 40 insertions(+), 271 deletions(-)

diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 { {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that is allowed in a {#link|function|Functions#}. </p> - <aside> - By convention, non-named tests should only be used to {#link|make other tests run|Nested Container Tests#}. - Non-named tests cannot be {#link|filtered|Skip Tests#}. - </aside> + <p>Non-named test blocks always run during test builds and are exempt from + {#link|Skip Tests#}.</p> <p> Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit return type of {#syntax#}test{#endsyntax#} is the {#link|Error Union Type#} {#syntax#}anyerror!void{#endsyntax#}, @@ -1173,74 +1171,6 @@ fn addOne(number: i32) i32 { </p> {#see_also|The Global Error Set|Grammar#} {#header_close#} - {#header_open|Nested Container Tests#} - <p> - When the <kbd>zig test</kbd> tool is building a test runner, only resolved {#syntax#}test{#endsyntax#} - declarations are included in the build. Initially, only the given Zig source file's top-level - declarations are resolved. Unless nested {#link|containers|Containers#} are referenced from a top-level test declaration, - nested container tests will not be resolved. - </p> - <p> - The code sample below uses the {#syntax#}std.testing.refAllDecls(@This()){#endsyntax#} function call to - reference all of the containers that are in the file including the imported Zig source file. The code - sample also shows an alternative way to reference containers using the {#syntax#}_ = C;{#endsyntax#} - syntax. This syntax tells the compiler to ignore the result of the expression on the right side of the - assignment operator. - </p> - {#code_begin|test|testing_nested_container_tests#} -const std = @import("std"); -const expect = std.testing.expect; - -// Imported source file tests will run when referenced from a top-level test declaration. -// The next line alone does not cause "testing_introduction.zig" tests to run. -const imported_file = @import("testing_introduction.zig"); - -test { - // To run nested container tests, either, call `refAllDecls` which will - // reference all declarations located in the given argument. - // `@This()` is a builtin function that returns the innermost container it is called from. - // In this example, the innermost container is this file (implicitly a struct). - std.testing.refAllDecls(@This()); - - // or, reference each container individually from a top-level test declaration. - // The `_ = C;` syntax is a no-op reference to the identifier `C`. - _ = S; - _ = U; - _ = @import("testing_introduction.zig"); -} - -const S = struct { - test "S demo test" { - try expect(true); - } - - const SE = enum { - V, - - // This test won't run because its container (SE) is not referenced. - test "This Test Won't Run" { - try expect(false); - } - }; -}; - -const U = union { // U is referenced by the file's top-level test declaration - s: US, // and US is referenced here; therefore, "U.Us demo test" will run - - const US = struct { - test "U.US demo test" { - // This test is a top-level test declaration for the struct. - // The struct is nested (declared) inside of a union. - try expect(true); - } - }; - - test "U demo test" { - try expect(true); - } -}; - {#code_end#} - {#header_close#} {#header_open|Test Failure#} <p> The default test runner checks for an {#link|error|Errors#} returned from a test. @@ -2856,9 +2786,11 @@ test "volatile" { </p> {#header_close#} <p> - To convert one pointer type to another, use {#link|@ptrCast#}. This is an unsafe - operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other - conversions are not possible. + {#link|@ptrCast#} converts a pointer's element type to another. This + creates a new pointer that can cause undetectable illegal behavior + depending on the loads and stores that pass through it. Generally, other + kinds of type conversions are preferable to + {#syntax#}@ptrCast{#endsyntax#} if possible. </p> {#code_begin|test|test_pointer_casting#} const std = @import("std"); @@ -5075,12 +5007,12 @@ test "if error union with optional" { {#see_also|Optionals|Errors#} {#header_close#} {#header_open|defer#} + <p>Executes an expression unconditionally at scope exit.</p> {#code_begin|test|test_defer#} const std = @import("std"); const expect = std.testing.expect; const print = std.debug.print; -// defer will execute an expression at the end of the current scope. fn deferExample() !usize { var a: usize = 1; @@ -5097,10 +5029,14 @@ fn deferExample() !usize { test "defer basics" { try expect((try deferExample()) == 5); } + {#code_end#} + <p>Defer expressions are evaluated in reverse order.</p> + {#code_begin|test|defer_unwind#} +const std = @import("std"); +const expect = std.testing.expect; +const print = std.debug.print; -// If multiple defer statements are specified, they will be executed in -// the reverse order they were run. -fn deferUnwindExample() void { +test "defer unwinding" { print("\n", .{}); defer { @@ -5116,13 +5052,9 @@ fn deferUnwindExample() void { } } } - -test "defer unwinding" { - deferUnwindExample(); -} {#code_end#} + <p>Inside a defer expression the return statement is not allowed.</p> {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#} -// Inside a defer expression the return statement is not allowed. fn deferInvalidExample() !void { defer { return error.DeferError; @@ -5131,50 +5063,6 @@ fn deferInvalidExample() !void { return error.DeferError; } {#code_end#} - {#code_begin|test|test_errdefer#} -const std = @import("std"); -const print = std.debug.print; - -// The errdefer keyword is similar to defer, but will only execute if the -// scope returns with an error. -// -// This is especially useful in allowing a function to clean up properly -// on error, and replaces goto error handling tactics as seen in c. -fn deferErrorExample(is_error: bool) !void { - print("\nstart of function\n", .{}); - - // This will always be executed on exit - defer { - print("end of function\n", .{}); - } - - errdefer { - print("encountered an error!\n", .{}); - } - - if (is_error) { - return error.DeferError; - } -} - -// The errdefer keyword also supports an alternative syntax to capture the -// generated error. -// -// This is useful for printing an additional error message during clean up. -fn deferErrorCaptureExample() !void { - errdefer |err| { - std.debug.print("the error is {s}\n", .{@errorName(err)}); - } - - return error.DeferError; -} - -test "errdefer unwinding" { - deferErrorExample(false) catch {}; - deferErrorExample(true) catch {}; - deferErrorCaptureExample() catch {}; -} - {#code_end#} {#see_also|Errors#} {#header_close#} {#header_open|unreachable#} @@ -8660,7 +8548,8 @@ test "decl access by string" { <pre>{#syntax#}@floatFromInt(int: anytype) anytype{#endsyntax#}</pre> <p> Converts an integer to the closest floating point representation. The return type is the inferred result type. - To convert the other way, use {#link|@intFromFloat#}. This cast is always safe. + To convert the other way, use {#link|@intFromFloat#}. This operation is legal + for all values of all integer types. </p> {#header_close#} @@ -10873,6 +10762,9 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/'; Some examples of tasks the build system can help with: </p> <ul> + <li>Performing tasks in parallel and caching the results.</li> + <li>Depending on other projects.</li> + <li>Providing a package for other projects to depend on.</li> <li>Creating build artifacts by executing the Zig compiler. This includes building Zig source code as well as C and C++ source code.</li> <li>Capturing user-configured options and using those options to configure @@ -10891,148 +10783,10 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/'; to see a command-line usage help menu. This will include project-specific options that were declared in the build.zig script. </p> - - {#header_open|Building an Executable#} - <p>This <code class="file">build.zig</code> file is automatically generated - by <kbd>zig init-exe</kbd>.</p> - {#code_begin|syntax|build_executable#} -const std = @import("std"); - -// Although this function looks imperative, note that its job is to -// declaratively construct a build graph that will be executed by an external -// runner. -pub fn build(b: *std.Build) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard optimization options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not - // set a preferred release mode, allowing the user to decide how to optimize. - const optimize = b.standardOptimizeOption(.{}); - - const exe = b.addExecutable(.{ - .name = "example", - // In this case the main source file is merely a path, however, in more - // complicated build scripts, this could be a generated file. - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - }); - - // This declares intent for the executable to be installed into the - // standard location when the user invokes the "install" step (the default - // step when running `zig build`). - b.installArtifact(exe); - - // This *creates* a Run step in the build graph, to be executed when another - // step is evaluated that depends on it. The next line below will establish - // such a dependency. - const run_cmd = b.addRunArtifact(exe); - - // By making the run step depend on the install step, it will be run from the - // installation directory rather than directly from within the cache directory. - // This is not necessary, however, if the application depends on other installed - // files, this ensures they will be present and in the expected location. - run_cmd.step.dependOn(b.getInstallStep()); - - // This allows the user to pass arguments to the application in the build - // command itself, like this: `zig build run -- arg1 arg2 etc` - if (b.args) |args| { - run_cmd.addArgs(args); - } - - // This creates a build step. It will be visible in the `zig build --help` menu, - // and can be selected like this: `zig build run` - // This will evaluate the `run` step rather than the default, which is "install". - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - // Creates a step for unit testing. This only builds the test executable - // but does not run it. - const unit_tests = b.addTest(.{ - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - }); - - const run_unit_tests = b.addRunArtifact(unit_tests); - - // Similar to creating the run step earlier, this exposes a `test` step to - // the `zig build --help` menu, providing a way for the user to request - // running the unit tests. - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&run_unit_tests.step); -} - {#code_end#} - {#header_close#} - - {#header_open|Building a Library#} - <p>This <code class="file">build.zig</code> file is automatically generated - by <kbd>zig init-lib</kbd>.</p> - {#code_begin|syntax|build_library#} -const std = @import("std"); - -// Although this function looks imperative, note that its job is to -// declaratively construct a build graph that will be executed by an external -// runner. -pub fn build(b: *std.Build) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard optimization options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not - // set a preferred release mode, allowing the user to decide how to optimize. - const optimize = b.standardOptimizeOption(.{}); - - const lib = b.addStaticLibrary(.{ - .name = "example", - // In this case the main source file is merely a path, however, in more - // complicated build scripts, this could be a generated file. - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - }); - - // This declares intent for the library to be installed into the standard - // location when the user invokes the "install" step (the default step when - // running `zig build`). - b.installArtifact(lib); - - // Creates a step for unit testing. This only builds the test executable - // but does not run it. - const main_tests = b.addTest(.{ - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - }); - - const run_main_tests = b.addRunArtifact(main_tests); - - // This creates a build step. It will be visible in the `zig build --help` menu, - // and can be selected like this: `zig build test` - // This will evaluate the `test` step rather than the default, which is "install". - const test_step = b.step("test", "Run library tests"); - test_step.dependOn(&run_main_tests.step); -} - {#code_end#} - {#header_close#} - - {#header_open|Compiling C Source Code#} - <pre>{#syntax#} -lib.addCSourceFile(.{ .file = .{ .path = "src/lib.c" }, .flags = &.{ - "-Wall", - "-Wextra", - "-Werror", - } }); - {#endsyntax#}</pre> - {#header_close#} - + <p> + For the time being, the build system documentation is hosted externally: + <a href="https://ziglang.org/learn/build-system/">Build System Documentation</a> + </p> {#header_close#} {#header_open|C#} <p> diff --git a/lib/std/Build.zig b/lib/std/Build.zig @@ -599,6 +599,11 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: self.h_dir = self.pathJoin(&h_list); } +/// Create a set of key-value pairs that can be converted into a Zig source +/// file and then inserted into a Zig compilation's module table for importing. +/// In other words, this provides a way to expose build.zig values to Zig +/// source code with `@import`. +/// Related: `Module.addOptions`. pub fn addOptions(self: *Build) *Step.Options { return Step.Options.create(self); } @@ -1031,6 +1036,11 @@ fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror! // TODO remove empty directories } +/// Creates a configuration option to be passed to the build.zig script. +/// When a user directly runs `zig build`, they can set these options with `-D` arguments. +/// When a project depends on a Zig package as a dependency, it programmatically sets +/// these options when calling the dependency's build.zig script as a function. +/// `null` is returned when an option is left to default. pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T { const name = self.dupe(name_raw); const description = self.dupe(description_raw); diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig @@ -318,6 +318,9 @@ pub fn addAnonymousImport(m: *Module, name: []const u8, options: CreateOptions) return addImport(m, name, module); } +/// Converts a set of key-value pairs into a Zig source file, and then inserts it into +/// the Module's import table with the specified name. This makes the options importable +/// via `@import("module_name")`. pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) void { addImport(m, module_name, options.createModule()); } diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig @@ -198,6 +198,8 @@ pub fn createModule(self: *Options) *std.Build.Module { /// deprecated: use `getOutput` pub const getSource = getOutput; +/// Returns the main artifact of this Build Step which is a Zig source file +/// generated from the key-value pairs of the Options. pub fn getOutput(self: *Options) LazyPath { return .{ .generated = &self.generated_file }; }