| ... | ... | @@ -381,7 +381,7 @@ |
| 381 | 381 | In this case, the {#syntax#}!{#endsyntax#} may be omitted from the return |
| 382 | 382 | type of <code>main</code> because no errors are returned from the function. |
| 383 | 383 | </p> |
| 384 | | {#see_also|Values|Tuples|@import|Errors|Root Source File|Source Encoding|try#} |
| 384 | {#see_also|Values|Tuples|@import|Errors|Entry Point|Source Encoding|try#} |
| 385 | 385 | {#header_close#} |
| 386 | 386 | {#header_open|Comments#} |
| 387 | 387 | <p> |
| ... | ... | @@ -823,7 +823,7 @@ |
| 823 | 823 | <kbd>zig test</kbd> is a tool that creates and runs a test build. By default, it builds and runs an |
| 824 | 824 | executable program using the <em>default test runner</em> provided by the {#link|Zig Standard Library#} |
| 825 | 825 | as its main entry point. During the build, {#syntax#}test{#endsyntax#} declarations found while |
| 826 | | {#link|resolving|Root Source File#} the given Zig source file are included for the default test runner |
| 826 | {#link|resolving|File and Declaration Discovery#} the given Zig source file are included for the default test runner |
| 827 | 827 | to run and report on. |
| 828 | 828 | </p> |
| 829 | 829 | <aside> |
| ... | ... | @@ -5222,7 +5222,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5222 | 5222 | <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li> |
| 5223 | 5223 | <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li> |
| 5224 | 5224 | </ul> |
| 5225 | | {#see_also|Root Source File#} |
| 5225 | {#see_also|Panic Handler#} |
| 5226 | 5226 | {#header_close#} |
| 5227 | 5227 | |
| 5228 | 5228 | {#header_open|@popCount#} |
| ... | ... | @@ -6480,14 +6480,155 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 6480 | 6480 | {#builtin#} |
| 6481 | 6481 | {#see_also|Build Mode#} |
| 6482 | 6482 | {#header_close#} |
| 6483 | | {#header_open|Root Source File#} |
| 6484 | | <p>TODO: explain how root source file finds other files</p> |
| 6485 | | <p>TODO: pub fn main</p> |
| 6486 | | <p>TODO: pub fn panic</p> |
| 6487 | | <p>TODO: if linking with libc you can use export fn main</p> |
| 6488 | | <p>TODO: order independent top level declarations</p> |
| 6489 | | <p>TODO: lazy analysis</p> |
| 6490 | | <p>TODO: using comptime { _ = @import() }</p> |
| 6483 | {#header_open|Compilation Model#} |
| 6484 | <p> |
| 6485 | A Zig compilation is separated into <em>modules</em>. Each module is a collection of Zig source files, |
| 6486 | one of which is the module's <em>root source file</em>. Each module can <em>depend</em> on any number of |
| 6487 | other modules, forming a directed graph (dependency loops between modules are allowed). If module A |
| 6488 | depends on module B, then any Zig source file in module A can import the <em>root source file</em> of |
| 6489 | module B using {#syntax#}@import{#endsyntax#} with the module's name. In essence, a module acts as an |
| 6490 | alias to import a Zig source file (which might exist in a completely separate part of the filesystem). |
| 6491 | </p> |
| 6492 | <p> |
| 6493 | A simple Zig program compiled with <code>zig build-exe</code> has two key modules: the one containing your |
| 6494 | code, known as the "main" or "root" module, and the standard library. Your module <em>depends on</em> |
| 6495 | the standard library module under the name "std", which is what allows you to write |
| 6496 | {#syntax#}@import("std"){#endsyntax#}! In fact, every single module in a Zig compilation &mdash; including |
| 6497 | the standard library itself &mdash; implicitly depends on the standard library module under the name "std". |
| 6498 | </p> |
| 6499 | <p> |
| 6500 | The "root module" (the one provided by you in the <code>zig build-exe</code> example) has a special |
| 6501 | property. Like the standard library, it is implicitly made available to all modules (including itself), |
| 6502 | this time under the name "root". So, {#syntax#}@import("root"){#endsyntax#} will always be equivalent to |
| 6503 | {#syntax#}@import{#endsyntax#} of your "main" source file (often, but not necessarily, named |
| 6504 | <code>main.zig</code>). |
| 6505 | </p> |
| 6506 | {#header_open|Source File Structs#} |
| 6507 | <p> |
| 6508 | Every Zig source file is implicitly a {#syntax#}struct{#endsyntax#} declaration; you can imagine that |
| 6509 | the file's contents are literally surrounded by {#syntax#}struct { ... }{#endsyntax#}. This means that |
| 6510 | as well as declarations, the top level of a file is permitted to contain fields: |
| 6511 | </p> |
| 6512 | {#code|TopLevelFields.zig#} |
| 6513 | <p> |
| 6514 | Such files can be instantiated just like any other {#syntax#}struct{#endsyntax#} type. A file's "root |
| 6515 | struct type" can be referred to within that file using {#link|@This#}. |
| 6516 | </p> |
| 6517 | {#header_close#} |
| 6518 | {#header_open|File and Declaration Discovery#} |
| 6519 | <p> |
| 6520 | Zig places importance on the concept of whether any piece of code is <em>semantically analyzed</em>; in |
| 6521 | essence, whether the compiler "looks at" it. What code is analyzed is based on what files and |
| 6522 | declarations are "discovered" from a certain point. This process of "discovery" is based on a simple set |
| 6523 | of recursive rules: |
| 6524 | </p> |
| 6525 | <ul> |
| 6526 | <li>If a call to {#syntax#}@import{#endsyntax#} is analyzed, the file being imported is analyzed.</li> |
| 6527 | <li>If a type (including a file) is analyzed, all {#syntax#}comptime{#endsyntax#}, {#syntax#}usingnamespace{#endsyntax#}, and {#syntax#}export{#endsyntax#} declarations within it are analyzed.</li> |
| 6528 | <li>If a type (including a file) is analyzed, and the compilation is for a {#link|test|Zig Test#}, and the module the type is within is the root module of the compilation, then all {#syntax#}test{#endsyntax#} declarations within it are also analyzed.</li> |
| 6529 | <li>If a reference to a named declaration (i.e. a usage of it) is analyzed, the declaration being referenced is analyzed. Declarations are order-independent, so this reference may be above or below the declaration being referenced, or even in another file entirely.</li> |
| 6530 | </ul> |
| 6531 | <p> |
| 6532 | That's it! Those rules define how Zig files and declarations are discovered. All that remains is to |
| 6533 | understand where this process <em>starts</em>. |
| 6534 | </p> |
| 6535 | <p> |
| 6536 | The answer to that is the root of the standard library: every Zig compilation begins by analyzing the |
| 6537 | file <code>lib/std/std.zig</code>. This file contains a {#syntax#}comptime{#endsyntax#} declaration |
| 6538 | which imports {#syntax#}lib/std/start.zig{#endsyntax#}, and that file in turn uses |
| 6539 | {#syntax#}@import("root"){#endsyntax#} to reference the "root module"; so, the file you provide as your |
| 6540 | main module's root source file is effectively also a root, because the standard library will always |
| 6541 | reference it. |
| 6542 | </p> |
| 6543 | <p> |
| 6544 | It is often desirable to make sure that certain declarations &mdash; particularly {#syntax#}test{#endsyntax#} |
| 6545 | or {#syntax#}export{#endsyntax#} declarations &mdash; are discovered. Based on the above rules, a common |
| 6546 | strategy for this is to use {#syntax#}@import{#endsyntax#} within a {#syntax#}comptime{#endsyntax#} or |
| 6547 | {#syntax#}test{#endsyntax#} block: |
| 6548 | </p> |
| 6549 | {#syntax_block|zig|force_file_discovery.zig#} |
| 6550 | comptime { |
| 6551 | // This will ensure that the file 'api.zig' is always discovered (as long as this file is discovered). |
| 6552 | // It is useful if 'api.zig' contains important exported declarations. |
| 6553 | _ = @import("api.zig"); |
| 6554 | |
| 6555 | // We could also have a file which contains declarations we only want to export depending on a comptime |
| 6556 | // condition. In that case, we can use an `if` statement here: |
| 6557 | if (builtin.os.tag == .windows) { |
| 6558 | _ = @import("windows_api.zig"); |
| 6559 | } |
| 6560 | } |
| 6561 | |
| 6562 | test { |
| 6563 | // This will ensure that the file 'tests.zig' is always discovered (as long as this file is discovered), |
| 6564 | // if this compilation is a test. It is useful if 'tests.zig' contains tests we want to ensure are run. |
| 6565 | _ = @import("tests.zig"); |
| 6566 | |
| 6567 | // We could also have a file which contains tests we only want to run depending on a comptime condition. |
| 6568 | // In that case, we can use an `if` statement here: |
| 6569 | if (builtin.os.tag == .windows) { |
| 6570 | _ = @import("windows_tests.zig"); |
| 6571 | } |
| 6572 | } |
| 6573 | |
| 6574 | const builtin = @import("builtin"); |
| 6575 | {#end_syntax_block#} |
| 6576 | {#header_close#} |
| 6577 | {#header_open|Special Root Declarations#} |
| 6578 | <p> |
| 6579 | Because the root module's root source file is always accessible using |
| 6580 | {#syntax#}@import("root"){#endsyntax#}, is is sometimes used by libraries &mdash; including the Zig Standard |
| 6581 | Library &mdash; as a place for the program to expose some "global" information to that library. The Zig |
| 6582 | Standard Library will look for several declarations in this file. |
| 6583 | </p> |
| 6584 | {#header_open|Entry Point#} |
| 6585 | <p> |
| 6586 | When building an executable, the most important thing to be looked up in this file is the program's |
| 6587 | <em>entry point</em>. Most commonly, this is a function named {#syntax#}main{#endsyntax#}, which |
| 6588 | {#syntax#}std.start{#endsyntax#} will call just after performing important initialization work. |
| 6589 | </p> |
| 6590 | <p> |
| 6591 | Alternatively, the presence of a declaration named {#syntax#}_start{#endsyntax#} (for instance, |
| 6592 | {#syntax#}pub const _start = {};{#endsyntax#}) will disable the default {#syntax#}std.start{#endsyntax#} |
| 6593 | logic, allowing your root source file to export a low-level entry point as needed. |
| 6594 | </p> |
| 6595 | {#code|entry_point.zig#} |
| 6596 | <p> |
| 6597 | If the Zig compilation links libc, the {#syntax#}main{#endsyntax#} function can optionally be an |
| 6598 | {#syntax#}export fn{#endsyntax#} which matches the signature of the C <code>main</code> function: |
| 6599 | </p> |
| 6600 | {#code|libc_export_entry_point.zig#} |
| 6601 | <p> |
| 6602 | {#syntax#}std.start{#endsyntax#} may also use other entry point declarations in certain situations, such |
| 6603 | as {#syntax#}wWinMain{#endsyntax#} or {#syntax#}EfiMain{#endsyntax#}. Refer to the |
| 6604 | {#syntax#}lib/std/start.zig{#endsyntax#} logic for details of these declarations. |
| 6605 | </p> |
| 6606 | {#header_close#} |
| 6607 | {#header_open|Standard Library Options#} |
| 6608 | <p> |
| 6609 | The standard library also looks for a declaration in the root module's root source file named |
| 6610 | {#syntax#}std_options{#endsyntax#}. If present, this declaration is expected to be a struct of type |
| 6611 | {#syntax#}std.Options{#endsyntax#}, and allows the program to customize some standard library |
| 6612 | functionality, such as the {#syntax#}std.log{#endsyntax#} implementation. |
| 6613 | </p> |
| 6614 | {#code|std_options.zig#} |
| 6615 | {#header_close#} |
| 6616 | {#header_open|Panic Handler#} |
| 6617 | <p> |
| 6618 | The Zig Standard Library looks for a declaration named {#syntax#}panic{#endsyntax#} in the root module's |
| 6619 | root source file. If present, it is expected to be a namespace (container type) with declarations |
| 6620 | providing different panic handlers. |
| 6621 | </p> |
| 6622 | <p> |
| 6623 | See {#syntax#}std.debug.simple_panic{#endsyntax#} for a basic implementation of this namespace. |
| 6624 | </p> |
| 6625 | <p> |
| 6626 | Overriding how the panic handler actually outputs messages, but keeping the formatted safety panics |
| 6627 | which are enabled by default, can be easily achieved with {#syntax#}std.debug.FullPanic{#endsyntax#}: |
| 6628 | </p> |
| 6629 | {#code|panic_handler.zig#} |
| 6630 | {#header_close#} |
| 6631 | {#header_close#} |
| 6491 | 6632 | {#header_close#} |
| 6492 | 6633 | {#header_open|Zig Build System#} |
| 6493 | 6634 | <p> |