https://github.com/zerodaycode/zork
Project manager and builder automation tool for modern C++ projects
https://github.com/zerodaycode/zork
build-system cpp cpp20 cpp20-modules cpp23
Last synced: 2 months ago
JSON representation
Project manager and builder automation tool for modern C++ projects
- Host: GitHub
- URL: https://github.com/zerodaycode/zork
- Owner: zerodaycode
- License: mit
- Created: 2022-02-01T15:14:34.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-09-22T09:15:56.000Z (over 1 year ago)
- Last Synced: 2025-04-25T08:42:47.472Z (8 months ago)
- Topics: build-system, cpp, cpp20, cpp20-modules, cpp23
- Language: Rust
- Homepage:
- Size: 239 MB
- Stars: 154
- Watchers: 5
- Forks: 11
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
The Zork++ project
A modern C++ project manager and build system for modern C++


[](https://github.com/zerodaycode/Zork/actions/workflows/release.yml)
[](https://github.com/zerodaycode/Zork/actions/workflows/code-quality.yml)
[](https://zerodaycode.github.io/Zork/index.html)
[](https://zerodaycode.github.io/Zork)
[](https://github.com/zerodaycode/Zork/issues)
[](https://github.com/zerodaycode/Zork/pulls)
[](/LICENSE)
---
[](https://github.com/zerodaycode/Zork/actions/workflows/tests-clang-linux.yml)
[](https://github.com/zerodaycode/Zork/actions/workflows/tests-gcc-linux.yml)
[](https://github.com/zerodaycode/Zork/actions/workflows/tests-gcc-windows.yml)
[](https://github.com/zerodaycode/Zork/actions/workflows/tests-msvc.yml)
---
# :memo: Table of Contents
[About](#-about-a-hrefabouta) **|** [Getting Started](#-getting-started-a-href--gettingstarteda) **|** [A quick start example](#generating-a-new-c-project-a-href--gettingstartedexamplea) **|** [The `zork.toml` reference guide](#-the-zorktoml-reference-guide-a-hrefzorktomlreferencea) **|** [The `Zork++` command_line](#-the-zork-command-line-interface-a-hrefzorkcommandlinea) **|** [Compilation Database (`compile_commands.json`)](#-compilation-database-a-hrefcompilation-databasea) **|** [C++23 `import std;`](#-c23-import-std-feature-a-hrefimportstda) **|** [The developers and contributors guide](#-developers-guide-a-hrefdevguidea) **|** [The future features](#-todo-zone-a-href--todozonea) **|** [Built Using](#-built-using-a-href--builtusinga) **|** [Contributing](./CONTRIBUTING.md) **|** [License](./LICENSE) **|** [Authors](#-authors-a-href--authorsa) **|** [Acknowledgements](#-acknowledgements-a-href--acknowledgementa)
`Zork++` was born out of the need to build `C++` projects with the *modules* feature, introduced in the `C++20` standard.
The existing build systems have limitations and difficulties using the `C++20` modules consistently.
So we started designing a tool that takes some `C++` files, generates the necessary compiler commands and invokes the compiler to produce the desired executable/library!
# :checkered_flag: Getting Started
## :computer: Installation
The easiest way to start with `Zork++` is to download the [latest release available](https://github.com/zerodaycode/Zork/releases) for your current operating system. The packages are built for the `x86_64` architecture.
### Windows
We provide an automated installer that installs the `Zork++` binary on your system and automatically adds the installation directory to the `PATH` environment variable.
Simply download the `windows-installer.zip` artifact from the release page, extract it and run the contained `zork-installer.exe`.
### Debian based Distributions
We provide a `.deb` package for Debian based distributions. After downloading it from the release page, install it by running the command
~~~bash
$ sudo apt install ./zork++.deb
~~~
### Arch Linux
The following packages are available in the AUR.
- `zork++`: Built from the sources of the latest release
- `zork++-git`: Built from the sources of the latest commit on the `main` branch
- `zork++-bin`: Installs a precompiled binary (fastest)
Using an AUR-helper such as `yay`:
~~~bash
$ yay -S zork++-bin
~~~
Or manually:
~~~bash
$ git clone https://aur.archlinux.org/zork++-bin.git && cd zork++-bin
$ makepkg -si
~~~
### Generic Linux package
We provide a generic `tar.gz` archive containing the executable and a `LICENSE`.
You can generally put the executable anywhere you like.
Be sure that the installation directory is found in the `PATH` environment variable, else it cannot be directly called from the command line without its installation path.
We recommend installing it in `/usr/bin`.
### macOS and another platforms
We currently don't provide installers or precompiled binaries for other operating systems.
You can build `Zork++` manually if your platform is a supported `Rust` target.
You can check out [the list of available targets here](https://doc.rust-lang.org/nightly/rustc/platform-support.html).
To build `Zork++` from scratch, download one of the `Source code` artifacts from the release page and extract it.
Then change into the `zork++` directory inside the extracted source code and run
~~~bash
$ cargo build --frozen --release
~~~
You can find the compiled binary inside the `target/release` directory.
## :pushpin: Prerequisites
In order to work with `Zork++`, you will need a `C++` a compiler on your system.
Currently, we are supporting the major three compilers in the ecosystem:
- LLVM's Clang
- GNU's GCC
- Microsoft's MSVC (only supported on Windows)
## :clap: Generating a new C++ project
You can use `Zork++` with an already existing project, or create a new project from the command line.
- Choose an empty folder to kick off with a fresh start.
- Assuming that you have `zork++` in `PATH`, type:
`$ zork++ new github_example`
After a moment, a new project should be created in your desired directory, where Clang will be set as the default compiler.
If you prefer to use one of the other two alternatives, just use:
`$ zork++ new github_example --compiler gcc` or `$ zork++ new github_example --msvc`
And after that, move inside the folder, and type:
`$ zork++ run`
An output similar to the one below should appear in your terminal
```stdout
[2023-02-08T20:03:25Z INFO Zork++] Launching a new Zork++ program
[2023-02-08T20:03:25Z INFO Zork++] [SUCCESS] - The process ended successfully, taking a total time in complete of: 349 ms
Hello from an autogenerated Zork project!
The program is running with: Clang
RESULT of 2 + 8 = 10
RESULT of 8 - 2 = 6
RESULT of 2 * 8 = 16
RESULT of 2 / 2 = 1
```
What happened here?
- We are calling the `zork++` executable previously installed on the system
- The command `new` instructs `zork++` to autogenerate a new `C++` *modules* project with the name `github_example`. The project contains a predetermined structure as shown below
- The parameter `--compiler clang` configures the project to use the `Clang` compiler
- With the `run` command, we are building the project based on the configuration that is written in the `zork_clang.toml` configuration file. After building the project, `Zork++` will automatically run the generated binary
*An autogenerated project using the `Zork++` command line*
### An overview of the autogenerated project structure
- `dependencies` ⇒ An empty folder. We recommend you to put your third-party or external libraries, headers, etc. in this folder.
- `ifc` ⇒ stands for *interfaces*. Here we put the *module interface units* of the project.
- `src` ⇒ where the *module implementation files* live.
- `tests` ⇒ where the *unit tests* and the *integration tests* of your new project are.
- `main.cpp` ⇒ The entry point for your `C++` program.
- `zork_clang.toml` ⇒ Finally! We arrived at the most important part that you will need to understand when working with `Zork++`.
See [The zork.toml config file](#zork_conf) section to have a better understanding on how to write the configuration file and your project.
> [!NOTE]
>
> This structure is just a guideline. You may prefer to organize your files in a completely different way. We are just providing a predefined layout, so you can quickly start working on your project.
>`Zork++` comes with this basic example by default, where is based on some driver code on the main file, a couple of module interfaces and module implementations. By passing `--template partitions` as a command line argument, you will have access to a more complex example, where module partitions and other module stuff appears, being a more sophisticated C++ modules project example.
## Let's explore the `out` directory a little
Here is where your compiler will place all the artifacts from the compilation and linkage process, including:
* The built executable / library
* Intermediate artifacts, such as object files and precompiled modules
* Some special folders, which are used internally by `Zork++`, such as the cache and some intrinsics.
Don't worry about them, they aren't relevant for the moment.
`Zork++` can build your project with different compilers at the same time.
To avoid collisions between the different build processes there is a separate directory for every compiler.
Let's go through the folders:
- `modules` ⇒ where the compiler places all the precompiled module interfaces, the object files for the `cpp` source files and so on.
- `zork/cache` ⇒ here we dump the cache files that store useful data to speed up the build process, to track some internally relevant data, or for storing the generated commands for the user to inspect (if you want to).
- `zork/intrinsics` ⇒ this is a special one. Sometimes `Zork++` needs additional things to work properly. This is the place where those things live. See [Windows special requirements](#windows_special_requeriments) for more info.
- `github_example.exe` ⇒ this is the binary, that is generated by the build process.
# :wrench: The `zork.toml` config file
The `zork.toml` configuration file is the core of the project.
It is the most important part for working with `Zork++`.
This is where you define the setup of your project, instructing `Zork++` to behave as you expect.
We are going to take the `zork.toml` from the [Getting started](#getting_started_example) example.
Here is the configuration file, that was generated above:
```toml
#This file it's autogenerated as an example of a Zork config file
[project]
name = "github-example"
authors = [ "Zero Day Code" ] # Replace this for the real authors
[compiler]
cpp_compiler = "clang"
cpp_standard = "20"
std_lib = "libc++" # This concrete property will only be applied to Clang
[build]
output_dir = "./out"
[modules]
base_ifcs_dir = "./github-example/ifc"
interfaces = [
{ file = 'math.cppm' }
]
base_impls_dir = "./github-example/src"
implementations = [
{ file = 'math.cpp' },
{ file = 'math2.cpp', dependencies = ['math'] }
]
sys_modules = ['iostream']
[targets.executable]
executable_name = "github-example"
sources = [
"./github-example/*.cpp"
]
[targets.tests]
tests_executable_name = "zork_proj_tests"
sources = [
"./github-example/*.cpp"
]
```
This is `toml` table syntax. You may choose whatever `toml` available syntax you prefer though.
For a full reference of every property available under a specific section, please see the [zork.toml](#zork_toml_reference) reference guide.
## Let's briefly discuss every section, to get a general perspective of what we are building
- `[project]` ⇒ Here you specify the metadata for the project. This could be potentially more relevant in the future, to allow users to auto-publish projects on some websites.
- `[compiler]` ⇒ The configuration for the `C++` compiler. From the desired compiler that you want to use, the desired language level of the C++ ISO standard, to the `std` library vendor that you want to link against.
For now, the `std_lib` is only considered when using Clang on a Unix system.
It is used to specify whether to use the `libc++` or `libstdc++` Standard library implementation.
- `[build]` ⇒ Specifics about how and where the generated files are dumped or treated. Here you specify where you want to create that directory.
- `[modules]` ⇒ The core section to instruct the compiler to work with `C++20 modules`. The most important attributes are the base path to the *interfaces* and *implementation* files (usually you don't want to spread your files elsewhere).
`Zork++` only looks for your `interfaces` and `implementation` files in the respective directories.
- `[targets.]` ⇒ Targets are named entries that are meant to produce a final product. Currently,
`Zork++` can produce *binary* products, *static libraries* and/or *dynamic libraries*.
- You can have as many *targets* you want and or you need. Or the reference section of this doc, you'll find all the
different options that you can use to configure every target.
- A very important note is that targets are processed in the declaration order of the configuration file, so be aware
of this fact when you do design your product lifecycle.
- Also,
Tests run independent of the executables or library generations. They are a shortcut alias to --targets
but with the particular behaviour that it will filter all the targets that include after the `.` in its
identifier the *word* `test` (any position, clasical 'contains'). Of course, you can mix them with the `--targets`
flag, so only *test* targets (with the *test* in its identifier) and the ones provided in the *CLI* argument
will be taking in consideration.
For example. Suppose that you have three different targets to test three different areas of your project.
Let's name them `test1`, `test2` and `test3`.
```bash
$ zork++ -v --targets test2,test3 test
```
For this `Zork++` invokation, it will only be processed and executed `test2` and `test3`.
To summarize: the `test` argument implies `build` + `run` but only for targets that contains a `test` substring
within its target identifier (which is the string after the `.` on the `[targets.]`) entry.
## :bulb: Additional notes on the `[modules]` attribute
> Whenever you declare a module interface or a module implementation in the configuration file, you must take in consideration that sometimes modules (both interfaces or implementations) depend on other modules. Dependencies of one or more modules are declared as shown below:
```toml
interfaces = [
{ file = 'math.cppm' }
]
implementations = [
{ file = 'math.cpp' }, # Direct mapping with the interface `math`
{ file = 'math2.cpp', dependencies = ['math'] }
# math2 isn't the same as math, so we need to specify the `math` dependency.
]
```
> The *module interface units* can take any number of module dependencies as they wish, but there's no direct mapping on the no dependency declaration, because it's an interface unit.
> On the implementations, if the relation has no declared dependencies, (meaning that only the file name of the *module implementation*
is declared here), `Zork++` will assume that the unique module interface that the module implementation depends on has the same name of the *file* property declared for the module implementation.
> A *module implementation unit* always depends on at least one interface unit: the *module interface* that public declared the module.
That's why `Zork++` assumes that if the implementation unit does not explicitly declare an interface unit, an interface unit exists with the same name in the interfaces' directory (without file extension).
> If the user does not use the same file name for both the interface and the declaration and no direct dependency is declared, a compiler error will be thrown because `Zork++` does not care about wrongly specified dependencies.
## Module partitions
One thing that we haven't discussed are `module partitions`. As described by the standard, there are two kinds of partitions, known as `module interface partitions` and `module implementation partitions` (or `internal partitions`). Both of them serve the same purpose: Allowing for better organization and modularization of the source code when projects start to grow larger or when you simply need a particular source code layout.
`Zork++` supports `module partitions` for every supported compiler, but they still have some peculiarities. Let's review them with an example:
```toml
[modules]
interfaces = [
{ file = 'interface_partition.cppm', partition = { module = 'partitions' } },
{ file = 'internal_partition.cpp', partition = { module = 'partitions', partition_name = 'internal_partition', is_internal_partition = true } },
{ file = 'partitions.cppm' }
]
```
*A closer look on how to work with module partitions within Zork++*
We included `partitions` inside the `interfaces` key because, most of the time, other module interfaces will require some partition, and having a separate key for them will break the way of letting you decide in which order the translation units must be processed.
So, whenever you see an *"interface"* that has a *partition* property, you must know that we are "downcasting" a module interface to some kind of partition.
Some peculiarities by compiler at the time of writing:
- GCC ⇒ NONE! GCC comes with a powerful module cache, so no further treatment is required. You can write module partitions without any worry to declare them in `Zork++`.
- Clang ⇒ This requires you to fully specify partitions, indicating the module property, which is the property that tells `Zork++` which is its related primary module interface, and the partition name. If partition name isn't present, we will assume the name of the partition file.
- MSVC ⇒ Basically, we take advantage of the fantastic `MSVC` implicit module lookup.
This means that you aren't obligated to explicitly declare module names or module partition names... But, there's a specific case: `internal module partitions`. So, whenever you have an internal module partition, you must declare your translation unit as `partition`, and then provide at least `module` and `is_internal_partition` in order to make it work
> [!NOTE]
>
> In future releases, things about module partitions may change drastically (or not!). For example, we are expecting Clang to implement a good way of making implicit declarations but having the opportunity to specify a concrete output directory, among other things in other compilers too.
## The sys_modules property
`Clang` and `GCC` require pre-compiling the classical system headers, before they are importable as modules.
For example, whenever you use `import ` instead of using `#include` directives.
Every time you want to use `import` in your project, you can instruct `Zork` to precompile the corresponding system header in order to make it available as module.
# :bookmark_tabs: The `zork.toml` reference guide
Here is an overview of all the attributes available in the `zork.toml` configuration file.
The format is described as `Rust` types (simplified).
Members marked as `Option` are optional attributes, all other members are mandatory.
```Rust
/// The complete hierarchy of keys
ZorkConfigFile {
project: ProjectAttribute,
compiler: CompilerAttribute,
build: Option,
executable: Option,
modules: Option,
tests: Option,
}
/// The [project] key
ProjectAttribute {
name: str
authors: Option>,
compilation_db : bool
code_root: str // A joinable path after the project root to add to every translation unit
}
/// The [compiler] key
CompilerAttribute {
cpp_compiler: CppCompiler, // clang, msvc or gcc
driver_path: Option, // The invokable name for the compiler's binary
cpp_standard: LanguageLevel, // but as a string, for ex: '20'
std_lib: Option, // Only relevant for clang: libc++ or stdlibc++
std_lib_installed_dir: Option, // the standard modules directory. If not present, Zork++ will try to find them anyway
extra_args: Option>
}
/// The [build] key
BuildAttribute {
output_dir: Option,
}
/// The [targets.] key
/// Any value after targets. will be used as the user's defined identifier for the target
/// Any entry in this format will be a new [`TargetAttribute`] which determines the final
/// product generated by `Zork++`
targets: Map
/// [`TargetAttribute`] - The type for holding the build details of every
/// user defined target
/// * `output_name`- The name with which the final byproduct will be generated
/// * `sources` - The sources to be included in the compilation of this target
/// * `extra_args` - Holds extra arguments that the user wants to introduce
/// * `kind` - Determined which type of byproduct will be generated (binary, library...)
TargetAttribute {
output_name: Option,
sources: Option>,
extra_args: Option>,
kind: Option,
}
/// [`ModulesAttribute`] - The core section to instruct the compiler to work with C++20 modules. The most important are the base path to the interfaces and implementation files
/// * `base_ifcs_dir`- Base directory. So you don't have to specify the full path of the interface files
/// * `interfaces` - A list to define the module interface translation units for the project
/// * `base_impls_dir` - Base directory. So you don't have to specify the full path of the implementation files
/// * `implementations` - A list to define the module interface translation units for the project
/// * `sys_modules` - An array field explicitly declare which system headers must be precompiled
ModulesAttribute {
base_ifcs_dir: Option,
interfaces: Option>,
base_impls_dir: Option,
implementations: Option>,
sys_modules: Option>,
}
## A closer look on the `ModulesAttribute` key
```Rust
/// [`ModuleInterface`] - A module interface structure for dealing
/// with the parse work of prebuilt module interface units
///
/// * `file`- The path of a primary module interface
/// (relative to base_ifcs_path if applies)
///
/// * `module_name` - An optional field for make an explicit
/// declaration of the C++ module on this module interface
/// with the `export module 'module_name' statement.
/// If this attribute isn't present, Zork++ will assume that the
/// C++ module declared within this file is equals
/// to the filename
///
/// * `partition` - Whenever this attribute is present,
/// we are telling Zork++ that the actual translation unit
/// is a partition, either an interface partition
/// or an implementation partition unit
///
/// * `dependencies` - An optional array field for declare the module interfaces
/// in which this file is dependent on
ModuleInterface {
file: str,
module_name: Option,
partition: Option,
dependencies: Option>,
}
/// [`ModulePartition`] - Type for dealing with the parse work
/// of module partitions, either interfaces or implementations
///
/// * `module`- The interface module unit that this partitions belongs to
///
/// * `partition_name` - An optional field for explicitly declare the name of a module interface
/// partition, or a module implementation partition.
/// Currently this requirement is only needed if your partitions
/// file names aren't declared as the modules convention,
/// that is `module_name-partition_name.extension`
///
/// * `is_internal_partition` - Optional field for declare that
/// the module is actually a module for hold implementation
/// details, known as module implementation partitions.
/// This option only takes effect with MSVC
ModulePartition {
module: str,
partition_name: Option<&str>,
is_internal_partition: Option,
}
/// [`ModuleImplementation`] - Type for dealing with the parse work
/// of module implementation translation units
///
/// * `file`- The path of a primary module interface (relative to base_ifcs_path)
/// * `dependencies` - An optional array field for declare the module interfaces
/// in which this file is dependent on
ModuleImplementation<'a> {
file: str,
dependencies: Option>,
}
```
## Some specific configuration values
Some attributes are categorical, meaning only some predefined values are valid.
For example:
- The supported CPP standards (`compiler.cpp_standard`) ⇒ '20', '23', '1a', '2a', '2b', '1x', '2x' or 'latest'
- The supported compilers (`compiler.cpp_compiler`):
- `clang` ⇒ (alias = "CLANG", alias = "Clang", alias = "clang")
- `msvc` ⇒ (alias = "MSVC", alias = "Msvc", alias = "msvc")
- `gcc` ⇒ (alias = "MSVC", alias = "Msvc", alias = "msvc")
- The supported standard libraries to link against (`compiler.std_lib`, only applies to `Clang`) ⇒ `stdlibc++` or `libc++`
- Supported kind of targets
- `executable` => (alias = "Executable", alias = "executable", alias = "exe")
- `static_lib` => (alias = "StaticLib", alias = "static lib", alias = "static-lib", alias = "static_lib", alias = "staticlib")
- `dylib` => (alias = "DynamicLib", alias = "dynamic lib", alias = "dyn-lib", alias = "dyn_lib", alias = "dylib")
# :bookmark_tabs: The `Zork++` command line interface
`Zork++` comes with a minimalistic yet powerful command line interface.
Our direct intention was to mimic the standard way of working with `Rust`'s `Cargo` CLI,
as it is a world-class tool well known and valued.
To summarize, we are offering the following commands and arguments:
- `build` ⇒ just compiles the project for every target declared (unless filtered by cli args)
- `run` ⇒ compiles the project and then runs the generated binary for every target declared (unless filtered by cli args)
- `test` ⇒ compiles the project and then runs the binary generated for any [`targets.`] (unless filtered by cli args)
- `new` ⇒ generates a new `C++2X` template project with a minimal configuration and
a minimal setup. This command includes some arguments to make it more flexible, like:
- `--name ` ⇒ the name of the autogenerated project
- `--git` ⇒ initializes a new git empty repository
- `--compiler ` ⇒ indicates which of the compilers available within `Zork++`
should be used to set up the template
#### Arguments (they should be placed before the main subcommands described above)
- `--root` => instructs `Zork++` where is the working directory of the project, otherwise, the *cwd* from where
the `Zork++` binary was invokated will be used as the project's root.
- `--targets` => filters the targets by its declared name on the `targets.` entry that will be
processed in the current iteration. Expected to be formatted as: `--targets=target1,target2,target3`. NOTE: Empty
whitespaces won't be trim so `target1, target2` will evaluate to ["target1", " target2"].
- `--match-files` => Accepts an string value that will be used to perform a filter to the detected `Zork++`
configuration files present in the project. Acts like the classical `contains` method, by checking that the value
that you passed in is a substring of some of the detected config files.
- `--driver-path` => An optional flag to specify the location of the binary of the compiler's
frontend that the user want's to use. This is similar to the `driver-name` compiler configuration,
but passing it directly from the CMD.
- `--template` => Accepts `basic` or `partitions`. The first is the default value is this flag is not present.
Controls which kind of `C++` code template is generated.
- `-v` ⇒ Outputs more information to stdout. The classical `verbose` command line flag. You have until
`-vv`, which is the maximum verbosity allowed, that will unlock the trace level logs.
- `-c,`--clear-cache` ⇒ Clears the files in the cache, so, in the next iteration, cached items
must be processed again.
# :bookmark_tabs: Compilation Database
`Zork++` is able to generate a compilation database file, commonly known as `compile_commands.json`. This file is typically used by static code analyzers, IDE's and other tools to provide information about the status, the quality, problems, errors, suggestions and all kind of crazy things that the linting tools are able to do.
To enable this feature, you will need to put a flag property, under the `#[project]` table, named `compilation_db`.
```toml
#[project]
compilation_db = true
```
The file will be automatically generated the first time that `Zork++` sees this property on the configuration file, and will be regularly updated when changes are detected in the generated command lines, or when files are added/dropped from your project.
# :bookmark_tabs: C++23 `import std;` feature
The `C++23` standard is supposed to come with a nice feature to finally support modules in a real way, that is through the `import std;` statement.
This means that the whole standard library will be available as a single nice and neat component.
But this is not available in every compiler using `C++20`, and at the time of writing, they have only partial or no support at all for `C++23`, but some of them have their own kind of workarounds.
In `Zork++`, you have this feature enabled if:
- `Clang`:
- For `clang >= 18` => available by default. `Zork++` will try to discover and build the standard library modules
that are typically shipped with the `llvm`, `clang` and/or `libc++` for **llvm >= 18.1.2**. The user can provide manually
a path to the installed location on the filesystem by passing a path to the `std_lib_installed_dir` property under the
[compiler] attribute if needed (may be the case if you have different versions installed on your system).
- For `clang >= 15 and clang < 18` => clang modules via their *modulemap* feature will be used to get the `import std` feature. This is a
**llvm* and **clang** feature completely different from the standard modules, but can do the trick. Actually is broken
on *Windows* for some clang versions, and we're not sure if we plan to fix it, since we're discussing if we should even support it.
> In any case, make sure that you enabled *libc++* as your standard library in your **zork.toml** configuration file.
- `MSVC` => full support is available from `Zork++` *v0.9.0* onwards. No aditional user configuration required.
- `GCC` => We just don't know. We will be glad if some reader that knows about could give us some guidance in this regard. So there's
no `import std` feature nor workaround within `Zork++` for `GCC`
- As alternative, you can use `import ;` This is, individually import some specific system header as a module.
Needs an explicit pre-compilation process, and also needs to be declared on the `system_headers` array-like attribute.
This is supported by `Clang` and `GCC` (since we are not able to do an `import std` for `GCC` builds).
Contributing to `Zork++` is, technically, an easy task. You just have to open an issue and document some bug that you discovered or some feature that you would like to have.
If you want to solve the bug or contribute with a new feature by yourself, after creating the issue, just fork the repository, link a new branch to your fork from the base branch, and when you're happy with the proposal, open a PR for us to review!
## :ballot_box_with_check: Running the tests
We distinguish two kinds of tests in Zork:
### Unit tests
- These directly test different parts of the internal work of `Zork++`, trying to make a reliable system to work with.
### Integration tests
- Integration tests in Zork are focused on building different kind of `C++` projects under different operating systems.
All tests are running in different workflows that you can [check out here]().
Alternatively, you can always download the source code and run them in a local environment.
You will need to have `Rust` installed and change into the `zork++` directory.
Then you just need to run `$ cargo test --all`.
## :sparkles: The things that we desire to implement or upgrade in Zork++
- Support the Intel's C++ compiler (not a priority, but it would be nice)
- Take an eye on how the compilers are implementing the `C++23` `import std;` feature,
and then include it in `Zork++` by default (only `GCC` is missed ATM)
- Include and offer test frameworks directly in the project. That means integrating
third party test frameworks directly in `Zork++`
- [Rust](https://www.rust-lang.org/) - The full code is written on Rust
- [TOML](https://www.toml.io/) - We are using `toml` for the program configuration files
## TODO - Motivations for the style, etc
- [@pyzyryab](https://github.com/pyzyryab) - Idea and core work
- [@gbm25](https://github.com/gbm25) - Parsers and testing attribute integration
- [@TheHiddenOnSystem](https://github.com/TheHiddenOnSystem) - Actions for auto-publishing the releases of the project
- [@FoIP](https://github.com/foip) - Nice code changes and upgrades, especially in the Rust rewrite
See also the list of [contributors](https://github.com/zerodaycode/Zork/contributors) who participated in this project.
# :confetti_ball: Acknowledgements
- This project is largely inspired by [CMake](https://cmake.org/) and [Rust's Cargo](https://www.rust-lang.org/)

