Web Site now using Jekyll
New static Web site, now generated using Jekyll.
Static pages
There are many reasons to prefer static pages over dynamic ones. You may find some here. It turns out you just have to write some HTML/CSS files using your editor or IDE of choice and then send these files to a server. You can do this in a responsive way using BootStrap and with style using available templates, see e.g., HTML5UP.
There are limits to this approach.
First, changing the style of your Web site over time soon becomes a burden. A solution is never to change this style. I am sure you have already seen the nice no-css-no-javascript-HTML-2.0 pages that some people like in academia. But what you are not one of these? Further, what if your pages relate to data you gather with time? Of course, you could try to keep your data and your manually edited Web pages synchronized. Not fun.
Static page generators
A solution is to follow a data-and-generators approach. Using data, stored in a database or in files, you can generate not only up-to-date Web pages but also resumes, application files, etc. Nothing really new here. Indeed, I had used the TahChee python-based static Web site generator for some time.
The choice of a generation framework is vast, see here for example.
Jekyll
At a first step I would have liked to find one based on the new language I am learning, Kotlin. None. Grain, based on Groovy, and with support for the Gradle build system seems nice too. But a bit too young. So let’s go for Jekyll.
It’s quite simple to have a running Jekyll site:
- if you intend to publish your Web pages using GitHub pages, the good starting point is the very nice tutorial by Jonathan McGlone
- if not, you can simply follow the Jekyll quick-start guide.
Update: just found the Jekyll Tips site. Lots of interesting information here too.


Enable or disable all billing functionality across the site.
Enable PayPal payment gateway.
Allows testing PayPal payments with sandbox accounts.
{{errors.paypal_group}}
Enable Stripe payment gateway.
{{errors.stripe_group}}


黒の手番です。53 はどう動かしますか？


Domestic Hot Water System
None
Heat Exchanger
Instantaneous
Storage Tank
Unknown
Heat Exchanger
Instantaneous Water Heating Source
None
Combustion
ElectricResistance
Other
Unknown
Tank Volume
Unknown
Hot Water Distribution Type
None
Distributed
Looped
Other
Point-of-use
Unknown
Water Heater Efficiency
Water Heater Efficiency Type
None
Energy Factor
Thermal Efficiency
Capacity
Capacity Units
None
Btu/h
Btu/s
Klbs/h
MCF/day
MMBtu/h
MW
Mlbs/h
Other
Tons
W
cal/h
cfh
cfm
ft-lbf/h
ft-lbf/min
gpm
hp
kBtu/h
kW
kcf/h
lbs/h
therms/h
Manufacturer
Model Number
Quantity
Year Installed
Yearof Manufacture


AngularJS Form Validation Example
Username:
Username is required.
Email:
Email is required.
Invalid email address.
Reset


URL for RPM download. For example:
http://koji.fedoraproject.org/packages/:
You can put more urls separated by space. first found first served.
http://koji.fedoraproject.org/packages/ http://custom.koji:DPORT/
Warning: if build checkouted from later topUrl is found in earlier downloadUrl. It is downloaded instead of later! (See fixme in KojiBuildDownloaderdownloadRPM).


You are going to love our brand new show Re-Vibe that stars the Hughes Brothers' second generation of stars. It’s a fresh take on big hits from different eras and genres.
From the amazing choreography to the soaring vocals, the cast of Re-Vibe puts their own spin on these classics. Filled with rock-n-roll, torch music, R&B, pop, alternative, jazz, country, and more, Re-Vibe is a fast-moving show with all types of dazzling dancing—it’s truly music in motion! Add to that marvelous harmonies, fun costuming, incredible lighting, and great sound and this show is bound to steal hearts. While the cast of this show is READ MORE


I graduated from the University of Auckland last year with a Bachelor of Science majoring in Computer Science. Not long ago I completed my first programming job at the University of Auckland, designing and programming a game that is being used as a learning tool for students at the University of Auckland.


It only takes few minutes to design, publish and manage APIs in WSO2 API Manager
Use an existing API's endpoint or the API Swagger definition to create an API
Use an existing SOAP endpoint to create a managed API. Import the WSDL of the SOAP service
Design and prototype a new REST API
Design and prototype a new Websocket API


Taking your site to the next level
The Eleventy ecosystem is huge! There are official and community starters for almost any Glitch project you can dream up.
The best part is, no matter what starter you use, as long as you set your eleventy app to generated static site, you'll be able to take advantage of the feature on Glitch!
- Right now, your site is live on the web, with a real URL (a secure HTTPS address 🔒) that updates as soon as you make changes to your site or app.
💡 In the Glitch editor, click your project name in the top left, and in the menu that opens, select the name and type a new one. Your project will be live at the new address instantly.
- Add a domain to your new Glitch project! Just go to the Tools menu in the Glitch editor, and click on Custom Domains.
- Use the Share button in the editor to invite others in to edit your new Eleventy project by typing in their email or Glitch username.
💡 Make your code, or even your entire app, private to just those you invite, by upgrading your Glitch account.
- Use a full-powered Linux command line to manage your new Glitch project. Go to the Tools menu in the Glitch editor, and click Terminal to peek under the hood.
There are lots of Eleventy plugins you can also add to your project.
Some additional developments to try:
- Add a UI library like tailwind
- Use the Eleventy image library to optimize your blog images
🚀
Previous post: Layouts & Design
Next post: Next Steps


Glow KeyboardEvent
Key events fire in the right order for a quick alphanumeric key press
Click here to begin the test
Click here to end the test
Test overlapping keys
Click here to begin the test
Click here to end the test
Test removing listeners
Click here to begin the test
Click here to end the test
Test delegating listeners


A program is a set of instructions for the computer. These instructions tell the computer precisely what to do, and the computer always follows these instructions. Just like people, computers can only follow instructions if specified in a language they can understand. These are called programming languages. There are very many languages that the computer can understand and Small Basic is one.
Imagine a conversation happening between you and your friend. You and your friends would use words, organized as sentences to convey information back and forth. Similarly, programming languages contain collections of words that can be organized into sentences that convey information to the computer. And programs are basically sets of sentences (sometimes just a few and sometimes many thousands) that together make sense to both the programmer and the computer alike. There are many languages that the computer can understand. Java, C++, Python, VB, etc. are all powerful modern computer languages that are used to develop simple to complex software programs.
A typical Small Basic program consists of a bunch programs statements . Every line of the program represents a statement and every statement is an instruction for the computer. When we ask the computer to execute a Small Basic program, it takes the program and reads the first statement. It understands what we’re trying to say and then executes our instruction. Once it’s done executing our first statement, it comes back to the program and reads and executes the second line. It continues to do so until it reaches the end of the program. That is when our program finishes.
TextWindow.WriteLine("Hello World")
This is a very simple program that consists of one statement That statement tells the computer to write a line of text which is Hello World, into the Text Window. It literally translates in the computer’s mind to: Write Hello World. You might have already noticed that the statement can in turn be split into smaller segments much like sentences can be split into words. In the first statement we have 3 distinct segments: a) TextWindow b) WriteLine c) “Hello World” The dot, parentheses and the quotes are all punctuations that have to be placed at appropriate positions in the statement, for the computer to understand our intent. You might remember the black window that appeared when we ran our first program. That black window is called the TextWindow or sometimes referred to as the Console. That is where the result of this program goes.
The TextWindowis called an object. There are a number of such objects available for us to use in our programs. We can perform several different operations on these objects. We’ve already used the WriteLine< operation in our program. You might also have noticed that the WriteLine operation is followed by Hello inside quotes. This text is passed as input
Punctuations such as quotes, spaces and parenthesis are very important in a computer out to the user. This is called an input to the program. Based on their position and count, operation. Some operations take one or more they can change the meaning of what is being inputs while others don’t take any͘ expressed.
Now that you have understood our first program, let’s go ahead and make it fancier by adding some colors.
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine("Hello World")
When you run the above program, you’ll notice that it prints out the same “Hello World” phrase inside TextWindow, but this time it prints it out in yellow instead of the gray that it did earlier.
Notice the new statement we added to our original program. It uses a new word, ForegroundColor which we equated to a value of “Yellow.” This means we’ve assigned “Yellow” to ForegroundColor. Now, the difference between ForegroundColor and the operation WriteLine is that ForegroundColor did not take any inputs nor did it need any parenthesis. Instead it was followed by an of TextWindow. Here is a list of values that are valid for the ForegroundColor property. Try replacing “Yellow” with one of these and see the results - don’t forget the quotes, they are required punctuations.


@* * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *@ @this(govukInput: GovukInput) @( form: Form[_], id: String, name: String, label: String, isPageHeading: Boolean, autocompleteOptions: Seq[String], headingMessageArgs: Seq[String] = Seq(), hint: Option[Html] = None )(implicit messages: Messages)


ABOUT
DOWNLOAD
CONTACT
SIGN IN
SIGN UP
Vocals4Locals
A platform for our local artists to showcase their talents
Connect with us on:


|
SRA Board Components
ESP-IDF component for SRA Board
|
#include "bar_graph.h"
Functions | |
| esp_err_t | enable_bar_graph () |
| enables the bar graph led's gpio pins More... | |
| esp_err_t | set_bar_graph (uint8_t data) |
| Set the value of bar graph LED. More... | |
| uint8_t | bool_to_uint8 (bool *input_array) |
| converts a boolean array of size 8 into 8-bit unsigned integer More... | |
| uint8_t bool_to_uint8 | ( | bool * | input_array | ) |
converts a boolean array of size 8 into 8-bit unsigned integer
| input_array | boolean input array of size 8 |
| esp_err_t enable_bar_graph | ( | ) |
enables the bar graph led's gpio pins
It will check for state of motor driver A and B, and accordingly init the free gpios.
| Motor Driver A | Motor Driver B | Mode |
|---|---|---|
| off | off | 1 |
| off | parallel | 2 |
| off | normal | 3 |
| parallel | off | 4 |
| parallel | parallel | 5 |
| parallel | normal | 6 |
| normal | off | 7 |
| normal | parallel | 8 |
| normal | normal | 0 |
enabled_bar_graph_flag is set to the value of Mode accordingly.
| esp_err_t set_bar_graph | ( | uint8_t | data | ) |
Set the value of bar graph LED.
The exact working of this is a bit hard to understand, so this is example. Below are the given states of motor drivers
Motor Driver A: Normal Motor Driver B: Off Mode = 7, so for mode = 7, mask = bitmask[7] = 0x0F = 00001111 data = 0xAA = 10101010
Since, motor driver A is in normal mode and motor driver B is off, we can only use IN5 - IN8 pins of the bar graph LED
Mask ==> 00001111 => 0x0F
Now, if data is 10101010, then even though pins IN1-IN4 are being used by motor driver, it will be set by gpio_set_level, which will crash the esp32 device. So, we check in the bitmask if the following pin is free or not, if bit is 1, it can be used, if it is 0, then it can't be used.
So, to achieve this we bitwise-and the mask with 0x80(10000000), if result is 0x80, then leftmost bit is 1, else it is 0. If leftmost bit is 1, means we can use this pin of bar graph, then we do the same thing with data, bitwise-and it with 0x80, to find the leftmost bit, if it is 1, the pin is set to 1, else 0. Now we left shift the data and mask variable.
| data | 8bit binary in hexadecimal form, i.e, the pattern that is needed to be shown on the bar graph LED |


FEATURED FASHION DRESS
WHY SHOP WITH US
DEDICATED SERVICE
Consult our specialists for help with an order, customization, or design advice.
Get in Touch >FREE RETURNS
We stand behind our goods and services and want you to be satisfied with them.
Get in Touch >INTERNATIONAL SHIPPING
Currently over 50 countries qualify for express international shipping.
Get in Touch >


| Created: | 6/26/2020 3:15:40 PM |
| Modified: | 6/26/2020 3:15:40 PM |
| Project: | |
| Advanced: |
| Attribute |
|
Public bigint fund_code_id |
|
Details:
|
|
Public varchar(255) fund_code_code |
|
Details:
|
|
Public varchar(255) fund_code_description |
|
Details:
|
|
Public varchar(255) fund_code_reporting_structure |
|
Details:
|
|
Public bigint fund_code_account_id |
|
Details:
|
|
Public varchar(255) fund_code_chapter_advances |
|
Details:
|
|
Public integer fund_code_enactment_year |
|
Details:
|
|
Public varchar(255) created_by |
|
Details:
|
|
Public varchar(255) updated_by |
|
Details:
|
|
Public timestamp with time zone(0) created_at |
|
Details:
|
|
Public timestamp with time zone(0) updated_at |
|
Details:
|
|
Public timestamp with time zone(0) start_date |
|
Details:
|
|
Public timestamp with time zone(0) end_date |
|
Details:
|
|
Public bigserial id |
|
Details:
|
|
Public jsonb ods_meta |
|
Details:
|
|
Public integer ods_version |
|
Details:
|
|
Public varchar(255) ods_created_by |
|
Details:
|
|
Public timestamp with time zone(0) ods_created_at |
|
Details:
|
| Operation | ||
|
Public fund_codes_pkey( id: bigserial, |
||
|
Details:
<<PK>>
|
| Tag | Value |
| Owner | public |
|
Details:
|
| Property | Value |
| isFinalSpecialization: | 0 |
| Object | Type | Connection | Direction | Notes |
| «view» current_fund_codes_view | View | Dependency | From | |
| «view» current_fund_codes_view | View | Dependency | From |


Total: $0.00     Reimbursable: $0.00
Comments:
Approved by:______________________ Date:______________


--- layout: default title: "My Resume" ---
Experience
Volkswagen Automotive CO., Ltd, China
Automotive Interior Engineer 2019.08 - 2020.09
Responsible for the mechanical design of the automotive interior door
- Participated in the research and development of the structure distribution of the Harman-Kardon metal speaker cover of the door panel;
- Designed an anti-collision pipe structure to optimize the performance of door panel in side crash experiment.
Department of Ophthalmology, LKS Faculty of Medicine, The University of Hong Kong
Research Assistant 2021.04 - Present | Hong Kong Inovation and Technology Funding
- Realize eye-tracking function with Virtual Reality headset and generate heatmap to monitor gaze direction;
- Build a fully designed tutorial system of Virtual Reality simulator for visual disability evaluation (previous paper).
Department of Biomedical Engineering, The Chinese University of Hong Kong
Research Intern 2021.06 - Present
Design for the mechanical package of the spectral domain-optical coherence tomography system
Projects
Virtual Reality Simulator for Visual Disability Evaluation
Responsible for upgrading the evaluation system to new Unity version and fulfill the tutorial function
- Design the tutorial system for patients to complete the evaluation testing more easily with English/Chinese Audio;
- Design the UI for technicians and file storage system for data post-processing;
- Fix the bugs and compatibility issues when upgrade the system for better performance.
Microsoft AirSim Reinforcement Learning in Unity
Integrate Microsoft AirSim for path following of autonomous quadrotor simulated in Unity with DQN network.
- Build a customized city environment in Unity and realize the autonomous drone to follow the city road with reinforcement learning;
- Modify the AirSim to Unity coordinate matching function for position and velocity feedback between the Unity and the AirSim wrapper.
Spectral Doman-Optical Coherence Tomograpy (SD-OCT) System Design
Design the package cover for the OCT engine and its rotary joint
- Modify the cover of the rotary joint to make it move parallelly with the translation stage;
- Design an accessory equipment for the rotary joint for simple and fast installation of the catheter;
- Rearrange the optical equitments and design a new package for OCT engine for portable usage.
Publications
Journal/Conference Papers
1. 3D-printed microprobe for ultrahigh-resolution optical coherence tomography imaging at 800 nm
Chao Xu, Yuhan Ju, Jiarui Wang, Peng Chen, Shaodi Zhu, Aaron H.P. Ho and Wu Yuan*
Photonics and Imaging in Biology and Medicine, submitted, 2021
English Proficiency
Recorded in 2017:
- GRE: Total 321+3.0 {Verbal 152(Over 56%) + Quantitative 169(Over 96%) + Analytical Writing 3.0}
- TOEFL: Total 95 {Reading 30 + Listening 27 + Speaking 17 + Writing 21}


Which value(s) are at the index at arr[3][2]?
int[][] arr = { {8, 3, 2}, {6, 7, 1}, {0, 5, 4}, {1, 2, 3}, }
3
1
4
2
5
There are not hints for this question


Welcome to My First Website
This is a heading
CLICK HERE TO SAVE THE DOLPHINS
This is a paragraph
Unordered lists
This is a item
Could put image here
Another item, but no picture


I am a cheeky nomad and artist surfing the cosmic waves, utilizing web development as a vehicle to have the freedom to meet people all over the world, and dance with them under the stars we all share.
I am experienced in leveraging agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.


zipnote - write the comments in zipfile to stdout, edit comments and rename files in zipfile
zipnote
zipfile
zipfile Zipfile to read comments from or edit.
-w Write comments to a zipfile from stdin (see below).
-b\ path Use path for the temporary zip file.
-h Show a short help.
-v Show version information.
-L Show software license.
zipnote writes the comments in a zipfile to stdout. This is the default mode. A second mode allows updating the comments in a zipfile as well as allows changing the names of the files in the zipfile. These modes are described below.
To write all comments in a zipfile to stdout use for example
zipnote foo.zip > foo.tmp
This writes all comments in the zipfile foo.zip to the file foo.tmp in a specific format.
If desired, this file can then be edited to change the comments and then used to update the zipfile.
zipnote -w foo.zip < foo.tmp
The names of the files in the zipfile can also be changed in this way. This is done by following lines like
"@ name"
in the created temporary file (called foo.tmp here) with lines like
"@=newname"
and then using the -w option as above.
The temporary file format is rather specific and zipnote is rather picky about it. It should be easier to change file names in a script.
Does not yet support large (> 2 GB) or split archives.
Info-ZIP


{% extends 'base.html' %} {% load static %} {% block content %}
I'm Sreejith Kalathil, 18 years old and a computer science student.My interest is to code and program using different languages and create various interefaces that could benifit the public. Currently seeking more knowledge in the subject to be a professional in the future.
If you've similar interest, fell free to check out our blog, where we share intriguing articles about the subject.
Some things you should know about me
My life started on 21st Oct,from a small and wide INDIAN family.I'm exploring around and reached down at UK for college at NEWCASTLE UNIVERSITY, class of 2021.
I aim to create a revolutionary software which could benefit the whole world. My interst is reiewing and studying various new technologies.
I've secured A*AA in A-Levels and I'll be pursuing computer science from Newcastle University.


|
||||||||||
| PREV NEXT | FRAMES NO FRAMES |
| Packages that use SymmetricEnc | |
|---|---|
| edu.biu.scapi.comm | |
| edu.biu.scapi.midLayer.asymmetricCrypto.encryption | |
| edu.biu.scapi.midLayer.symmetricCrypto.encryption |
| Uses of SymmetricEnc in edu.biu.scapi.comm |
|---|
| Constructors in edu.biu.scapi.comm with parameters of type SymmetricEnc | |
|---|---|
EncryptedChannel(Channel channel,
SymmetricEnc encScheme)
This public constructor can be used by anyone holding a channel that is connected. |
| Uses of SymmetricEnc in edu.biu.scapi.midLayer.asymmetricCrypto.encryption |
|---|
| Constructors in edu.biu.scapi.midLayer.asymmetricCrypto.encryption with parameters of type SymmetricEnc | |
|---|---|
ScElGamalKEM(DlogGroup dlogGroup,
KeyDerivationFunction kdf,
SymmetricEnc encryption,
int symKeySize)
Constructor that gets a DlogGroup, KDF and symmetric encryption and sets them. |
|
ScElGamalKEM(DlogGroup dlogGroup,
KeyDerivationFunction kdf,
SymmetricEnc encryption,
int symKeySize,
java.security.SecureRandom random)
Constructor that gets a DlogGroup, KDF, symmetric encryption and source of randomness. |
|
ScElGamalKEM(java.lang.String dlogName,
java.lang.String kdfName,
SymmetricEnc encryption,
int symKeySize)
Constructor that gets a DlogGroup name and kdf name to create and sets them to the underlying members. |
|
ScElGamalKEM(java.lang.String dlogName,
java.lang.String kdfName,
SymmetricEnc encryption,
int symKeySize,
java.lang.String randNumGenAlg)
Constructor that gets a DlogGroup name, kdf name and random number generator to use. |
| Uses of SymmetricEnc in edu.biu.scapi.midLayer.symmetricCrypto.encryption |
|---|
| Subinterfaces of SymmetricEnc in edu.biu.scapi.midLayer.symmetricCrypto.encryption | |
|---|---|
interface |
AuthenticatedEnc
|
interface |
CBCEnc
|
interface |
CTREnc
Any implementation of Symmetric encryption in Counter-Mode ash to implement this interface. |
interface |
SymAdditiveHomomorphicEnc
General interface for symmetric additive homomorphic encryption. |
interface |
SymMultiplicativeHomomorphicEnc
General interface for symmetric multiplicative homomorphic encryption. |
| Classes in edu.biu.scapi.midLayer.symmetricCrypto.encryption that implement SymmetricEnc | |
|---|---|
class |
OpenSSLCBCEncRandomIV
This class performs the Cipher Block Chaining (CBC) Mode encryption and decryption, using OpenSSL library. |
class |
OpenSSLCTREncRandomIV
This class performs the randomized Counter (CTR) Mode encryption and decryption, using OpenSSL library. |
class |
OpenSSLEncWithIVAbs
This is an abstract class that manage the common behavior of symmetric encryption using Open SSL library. |
class |
ScCBCEncRandomIV
This class performs the Cipher Block Chaining (CBC) Mode encryption and decryption. |
class |
ScCTREncRandomIV
This class performs the randomized Counter Mode encryption and decryption. |
class |
ScEncryptThenMac
This class implements a type of authenticated encryption: encrypt then mac. |
| Constructors in edu.biu.scapi.midLayer.symmetricCrypto.encryption with parameters of type SymmetricEnc | |
|---|---|
ScEncryptThenMac(SymmetricEnc encryptor,
Mac mac)
Constructor that gets a SymmetricEncryption object and a Mac object and sets them as the underlying respective members. |
|
||||||||||
| PREV NEXT | FRAMES NO FRAMES |


--- layout: page title: About permalink: /about/ ---
The Authors of vluxe.io. Brothers, Twins, Builders, Computer Scientists. Making it up as we go.
{{ author.bio }}


Freelance front-end web developer and WordPress enthusiast based in Los Angeles.
Contact MeI'm a front-end developer with a passion for writing elegant code. I specialize in developing clean, beautiful webpages and dynamic WordPress sites for small businesses, nonprofit organizations, and artists.
Let's Get Started!I design with HTML(5), CSS(3), and a touch of JavaScript.
I create fully dynamic and custom WordPress websites.
I help make updates to your site to keep things fresh.
You have to make your websites with love these days!
Ready to start your next project? That's great! Give me a call or shoot me an email and I'll get back to you asap.


I am a project manager engaged in Salesforce consulting, a programmer, tech hobbyist, husband, dad, and I like Jesus.
On occasion, I get that list of identities in the right order.
You are welcome to contact me at<EMAIL_ADDRESS>I work at Candoris, a group of talented engineers and consultants supporting digital transformation, including Salesforce consulting. I love being surrounded by folks with both technical expertise and deep empathy for customers.


Psalms 99:1
The LORD reigneth; let the people tremble: he sitteth between the cherubims; let the earth be moved.


FOR THE DEAD
FIRST
(Easter:
Acts 10:34-43)
A reading from the second Book of Maccabees 12:43-45††† (Or Job 19:1, 23-27 )
In those days: Judas [the leader of Israel] also took up a collection, man by man, to the amount of two thousand drachmas of silver, and sent it to Jerusalem to provide for a sin offering. In doing this he acted very well and honourably, taking account of the resurrection. For if he were not expecting that those who had fallen would rise again, it would have been superfluous and foolish to pray for the dead. But if he was looking to the splendid reward that is laid up for those who fall asleep in godliness, it was a holy and pious thought. Therefore he made atonement for the dead, that they might be delivered from their sin.
The word of the Lord.
Or:
A reading from the Book of Job 19:1.23-27
Job answered: "Oh that my words were written! Oh that they were
inscribed in a book! Oh that with an iron pen and lead they were graven in the
rock for ever! For I know that my Redeemer lives, and at last he will stand
upon the earth; and after my skin has been thus destroyed, then from my flesh I
shall see God, whom I shall see on my side, and my eyes shall behold, and not
another.
Or:
A reading from the book of the Acts of the Apostles 10:34-43
In those days: Peter opened his mouth and said: "Truly I perceive
that God shows no partiality, but in every nation any one who fears him and
does what is right is acceptable to him. You know the word which he sent to
Israel, preaching good news of peace by Jesus Christ (he is Lord of all), the
word which was proclaimed throughout all Judea, beginning from Galilee after
the baptism which John preached: how God anointed Jesus of Nazareth with the Holy
Spirit and with power; how he went about doing good and healing all that were
oppressed by the devil, for God was with him. And we are witnesses to all that
he did both in the country of the Jews and in
The word of the Lord.
RESPONSORIAL PSALM Psalm 23†† (Or Psalm 130)
R. The Lord is my shepherd; there is nothing I shall want.
or
R. Though I walk in the valley of the shadow of death, no evil would I fear, for you are with me.
The LORD is my shepherd;
there is nothing I shall want. Fresh and green are the pastures where he gives
me repose. Near restful water he leads me; he revives my soul. He guides me
along the right path, for the sake of his name.
R.
The
Lord is my shepherd; there is nothing I shall want.
Though I should walk
in the valley of the shadow of death, no evil would I fear, for you are with
me.
R.
The
Lord is my shepherd; there is nothing I shall want.
You have prepared a
table before me in the sight of my foes. My head you have anointed with oil; my
cup is overflowing.
R.
The Lord
is my shepherd; there is nothing I shall want.
Surely goodness and
mercy shall follow me all the days of my life. In the LORDís own house shall I
dwell for length of days unending.
R.
The Lord
is my shepherd; there is nothing I shall want.
Or:
R. Out of the depths I cry to you, O Lord.
or
R. I hope in the Lord, I hope in his word.
Out of the depth I
cry to you, O LORD; Lord, hear my voice! O let your ears be attentive to the
sound of my pleading.
R.
Out of the depths I cry to you, O Lord.
If you, O LORD,
should mark iniquities, Lord, who could stand? But with you is
found forgiveness, that you may be revere.
R.
Out of the depths I cry to you, O Lord.
I long for you, O
LORD, my soul longs for his word. My soul hopes in the Lord, more than watchmen
for daybreak.
R.
Out of the depths I cry to you, O Lord.

It is he who will
redeem
R.
Out of the depths I cry to you, O Lord.
SECOND
A reading from the letter of St Paul to the Romans 5:5-11††† (Or Romans 8:14-23)
Brethren: Hope does
not disappoint us, because God's love has been poured into our hearts through
the Holy Spirit which has been given to us. While we were still weak, at the
right time Christ died for the ungodly. Why, one will hardly die for a
righteous man--though perhaps for a good man one will dare even to die. But God
shows his love for us in that while we were yet sinners Christ died for us.
Since, therefore, we are now justified by his blood, much more shall we be
saved by him from the wrath of God. For if while we were enemies we were
reconciled to God by the death of his Son, much more, now that we are
reconciled, shall we be saved by his life. Not only
so, but we also rejoice in God through our Lord Jesus Christ, through whom we
have now received reconciliation.
The word of the Lord
Or:
A reading from the letter of St Paul to the Romans 8:14-23
Brethren: All who are led by the Spirit of God are sons of God. For you did not receive the spirit of slavery to fall back into fear, but you have received the spirit of sonship. When we cry, "Abba! Father!" it is the Spirit himself bearing witness with our spirit that we are children of God, and if children, then heirs, heirs of God and fellow heirs with Christ, provided we suffer with him in order that we may also be glorified with him. I consider that the sufferings of this present time are not worth comparing with the glory that is to be revealed to us. For the creation waits with eager longing for the revealing of the sons of God; for the creation was subjected to futility, not of its own will but by the will of him who subjected it in hope; because the creation itself will be set free from its bondage to decay and obtain the glorious liberty of the children of God. We know that the whole creation has been groaning in travail together until now; and not only the creation, but we ourselves, who have the first fruits of the Spirit, groan inwardly as we wait for adoption as sons, the redemption of our bodies.
The word of the Lord.
R. Alleluia. Blessed are you, Father, Lord of heaven and earth, that you have revealed to little ones the mysteries of the kingdom.R. Alleluia.
GOSPEL
A reading from the holy Gospel according to Matthew 5:1-12††† (Or Matthew 11:25-30)
At that time: Seeing
the crowds, Jesus went up on the mountain, and when he sat down his disciples
came to him. And he opened his mouth and taught them, saying: "Blessed are
the poor in spirit, for theirs is the kingdom of heaven.
"Blessed are those who mourn, for they shall be comforted.
"Blessed are the meek, for they shall inherit the earth.
"Blessed are those who hunger and thirst for righteousness, for
they shall be satisfied. "Blessed are the merciful, for they shall obtain
mercy. "Blessed are the pure in heart, for they shall
see God. "Blessed are the peacemakers, for they shall be called sons of
God. "Blessed are those who are persecuted for
righteousness' sake, for theirs is the kingdom of heaven. "Blessed are you
when men revile you and persecute you and utter all kinds of evil against you
falsely on my account. Rejoice and be glad, for your reward is great in
heaven.
The Gospel of the Lord.
GOSPEL
A reading from the holy Gospel according to Matthew 11:25-30
At that time Jesus declared, "I thank you, Father, Lord of heaven and earth, that you have hidden these things from the wise and understanding and revealed them to babes; yes, Father, for such was your gracious will. All things have been delivered to me by my Father; and no one knows the Son except the Father, and no one knows the Father except the Son and any one to whom the Son chooses to reveal him. Come to me, all who labour and are heavy laden, and I will give you rest. Take my yoke upon you, and learn from me; for I am gentle and lowly in heart, and you will find rest for your souls. For my yoke is easy, and my burden is light."
The Gospel of the Lord.


--- name: partial-password-restore --- {{ flash() }} {% if invalidHash %} Invalid or expired link. {% endif %}
Please enter your email below, we will send you an email message with a link to enter a new password for your account.
E-mail Address


Zig is a general-purpose programming language designed for robustness, optimality, and maintainability. Zig is aggressively pursuing its goal of overthrowing C as the de facto language for system programming. Zig intends to be so practical that people find themselves using it even if they dislike it.
This release features 6 months of work and changes from 46 different contributors, spread among 875 commits.
Special thanks to my sponsors who provide financial support. You're making Zig sustainable.
{#header_open|Table of Contents#} {#nav#} {#header_close#} {#header_open|LLVM 8#}This release of Zig upgrades to LLVM 8. Zig operates in lockstep with LLVM; Zig 0.4.0 is not compatible with LLVM 7.
Notably this means that Zig now has {#link|WebAssembly Support#}, as well as recognizing the HermitCore and Hurd operating systems. On the other hand, support for the Nios II architecture is dropped, due to it being an experimental target which was largely unmaintained.
{#header_close#} {#header_open|FreeBSD Support#}Marc Tiehuis started an initial FreeBSD branch. Greg V picked up the figurative baton in #1661, and Marcio Giaxa completed the effort.
Now, FreeBSD works in the stage1 C++ compiler code, as well as the Zig Standard Library, which means it now has {#link|Tier 2 Support#}. To achieve {#link|Tier 1 Support#}, these things are needed:
Despite these issues, thanks to SourceHut, FreeBSD does have some CI testing support, as well as automated binary builds available for x86_64 on the download page.
See #1759 for more details.
{#header_close#} {#header_open|NetBSD Support#}Maya Rashish ported the stage1 C compiler as well as the Zig Standard Library to be compatible with NetBSD. Have a look at their writeup: Porting Zig to NetBSD - a fun, speedy port
NetBSD is limited to {#link|Tier 2 Support#} due to lack of a continuous integration service, as well as a missing implementation of {#link|building the system's libc startup files lazily from source|Zig ships with libc#}.
{#header_close#} {#header_open|WebAssembly Support#}Now that Zig uses {#link|LLVM 8#}, the wasm32
target architecture is
guaranteed to be available in Zig.
Ben Noordhuis fixed zig build-exe
for the wasm32
target
(#1570).
Shritesh Bhattarai added --allow-undefined
and --export-all
to the wasm linker line, solving #1622.
There may be a better way to catch link errors in the future, but for now, this makes
WebAssembly work out-of-the-box in Zig:
$ zig build-exe math.zig -target wasm32-freestanding
test.js
const fs = require('fs');
const source = fs.readFileSync("./math");
const typedArray = new Uint8Array(source);
WebAssembly.instantiate(typedArray, {
env: {
print: (result) => { console.log(`The result is ${result}`); }
}
}).then(result => {
const add = result.instance.exports.add;
add(1, 2);
});
$ node test.js
The result is 3
There is also the "WebAssembly System Interface" operating system target, wasi
.
I haven't really explored this use case yet, but I did make the C integer types work for it.
More research and exploration is needed.
Shawn Landden implemented arm64 Linux support in the Zig Standard Library, as well as the necessary stage1 C++ compiler changes.
The arm64-linux target has now graduated to {#link|Tier 2 Support#}. To achieve {#link|Tier 1 Support#}, we would need some way to run Continuous Integration tests on arm64 linux.
SourceHut has experimental arm64 Debian images, which may be worth looking into.
{#header_close#} {#header_open|UEFI Support#}GitHub user nebulaeonline approached the Zig project with an interesting use case: creating a UEFI application.
nebulaeonline submitted a pull request adding UEFI as a new operating system that Zig recognizes. The patch contained the linker configuration and a few updates to the Zig Standard Library.
With this patch merged, nebulaeonline went on to work on their UEFI barebones project. It looks like they ended up using C rather than Zig in the end, most likely due to Zig's lack of maturity. Here I have linked to the last revision before they removed the Zig code, in case anyone wants to poke around. Since then Zig has gained {#link|C Pointers#} which was a large pain point for nebulaeonline.
{#header_close#} {#header_open|Tier System#}Zig now uses a "support tier" system to communicate the level of support for different targets.
{#header_open|Explanation of Tiers#} {#header_open|Tier 1 Support#}zig targets
is guaranteed to include this target.zig targets
will
display the target if it is available.--emit asm
and cannot emit object files.| freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other | |
|---|---|---|---|---|---|---|---|---|
| x86_64 | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 1|Tier 1 Support#} | {#link|Tier 1|Tier 1 Support#} | {#link|Tier 1|Tier 1 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 3|Tier 3 Support#} |
| i386 | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} |
| arm | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} |
| arm64 | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 2|Tier 2 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} |
| bpf | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| hexagon | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| mips | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| powerpc | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| amdgcn | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| sparc | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| s390x | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| lanai | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | {#link|Tier 3|Tier 3 Support#} | {#link|Tier 3|Tier 3 Support#} | N/A | {#link|Tier 3|Tier 3 Support#} |
| wasm32 | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
| wasm64 | {#link|Tier 3|Tier 3 Support#} | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
| avr | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| riscv32 | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} |
| riscv64 | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} |
| xcore | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| nvptx | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| msp430 | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| r600 | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| arc | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| tce | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| le | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| amdil | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| hsail | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| spir | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| kalimba | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| shave | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
| renderscript | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | N/A | {#link|Tier 4|Tier 4 Support#} | {#link|Tier 4|Tier 4 Support#} | N/A | {#link|Tier 4|Tier 4 Support#} |
One of the main features of Zig is @cImport and {#link|C Translation|C Translation Status#}. This is accomplished by linking against Clang libraries. Clang is a fully featured C and C++ compiler. Zig has all this functionality - so we may as well expose it!
The zig cc
command exposes clang, which you can see with this amusing output:
$ zig cc --version
clang version 8.0.0
...
zig cc
is a bit of a low level command. The higher level command line
interface --c-source
(or the corresponding {#link|Zig Build System#} API)
is recommended instead, for a few reasons:
zig cc
represents a fresh build of clang, which does not have such patches.
This is actually A Good Thing - more on this below.
--c-source
:-march=native
is enabled for the native target.-target
, --color
, and
--strip
will apply to both C and Zig Code.Here's an example of Zig building some C code:
hello.c
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello world\n");
return 0;
}
$ zig build-exe --c-source hello.c --library c
$ ./hello
Hello world
You can use --verbose-cc
to see what C compiler command this executed:
$ zig build-exe --c-source hello.c --library c --verbose-cc
zig cc -MD -MV -MF zig-cache/tmp/42zL6fBH8fSo-hello.o.d -nostdinc -fno-spell-checking -isystem /home/andy/dev/zig/build/lib/zig/include -isystem /home/andy/dev/zig/build/lib/zig/libc/include/x86_64-linux-gnu -isystem /home/andy/dev/zig/build/lib/zig/libc/include/generic-glibc -isystem /home/andy/dev/zig/build/lib/zig/libc/include/x86_64-linux-any -isystem /home/andy/dev/zig/build/lib/zig/libc/include/any-linux-any -march=native -g -fstack-protector-strong --param ssp-buffer-size=4 -fno-omit-frame-pointer -o zig-cache/tmp/42zL6fBH8fSo-hello.o -c hello.c -fPIC
Note that if I run the command again, there is no output, and it finishes instantly:
$ time zig build-exe --c-source hello.c --library c --verbose-cc
real 0m0.027s
user 0m0.018s
sys 0m0.009s
This is thanks to {#link|Build Artifact Caching#}. Zig automatically parses the .d file that clang produces and uses a robust caching system to avoid duplicating work.
In the {#link|Zig Build System#}, {#syntax#}builder.addCExecutable{#endsyntax#} used to be a system C compiler driver. That functionality is deleted. Instead, build scripts can attach C source files to any executable, library, or object with {#syntax#}foo.addCSourceFile{#endsyntax#}. You can see a nice example of this in Michael Dusan's benchmark.unicode project.
Don't forget to use {#syntax#}foo.linkSystemLibrary("c");{#endsyntax#} if the C code expects to use libc.
You may have noticed that the
Zig-generated C compilation command included -nostdinc
.
This is a crucial step in the direction Zig is headed - providing consistent, reliable builds that are insulated from the system-specific differences in the wild.
This affects @cImport and
{#link|C Translation|C Translation Status#} as well. By default, Zig no longer looks in
system paths for C header files, instead relying only on what Zig ships and what
users explicitly request with -isystem
.
However, when one uses the {#link|Zig Build System#}, and uses {#syntax#}linkSystemLibrary{#endsyntax#} API, Zig takes that as a hint to look in system default search paths. Marc Tiehuis proposed to expose this functionality to the command line interface, and that is likely to be an accepted proposal.
Thanks to Akuli for adding /lib/x86_64-linux-gnu
or similar to default
system library search paths for zig build scripts.
One piece to this puzzle is that Zig now ships with libc. You can find the available
libc targets with zig targets
:
...
Available libcs:
aarch64_be-linux-gnu
aarch64_be-linux-musl
aarch64-linux-gnu
aarch64-linux-musleabi
armeb-linux-gnueabi
armeb-linux-gnueabihf
armeb-linux-musleabi
armeb-linux-musleabihf
arm-linux-gnueabi
arm-linux-gnueabihf
arm-linux-musleabi
arm-linux-musleabihf
i386-linux-gnu
i386-linux-musl
mips64el-linux-gnuabi64
mips64el-linux-gnuabin32
mips64el-linux-musl
mips64-linux-gnuabi64
mips64-linux-gnuabin32
mips64-linux-musl
mipsel-linux-gnu
mipsel-linux-musl
mips-linux-gnu
mips-linux-musl
powerpc64le-linux-gnu
powerpc64le-linux-musl
powerpc64-linux-gnu
powerpc64-linux-musl
powerpc-linux-gnu
powerpc-linux-musl
riscv32-linux-musl
riscv64-linux-gnu
riscv64-linux-musl
s390x-linux-gnu
s390x-linux-musl
sparc-linux-gnu
sparcv9-linux-gnu
x86_64-linux-gnu
x86_64-linux-gnux32
x86_64-linux-musl
What this means is that --library c
for these targets does not depend
on any system files!
Let's look at that C hello world example again:
$ zig build-exe --c-source hello.c --library c
$ ./hello
Hello world
$ ldd ./hello
linux-vdso.so.1 (0x00007ffd03dc9000)
libc.so.6 => /lib/libc.so.6 (0x00007fc4b62be000)
libm.so.6 => /lib/libm.so.6 (0x00007fc4b5f29000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fc4b5d0a000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fc4b5b06000)
librt.so.1 => /lib/librt.so.1 (0x00007fc4b58fe000)
/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc4b6672000)
glibc does not support building {#link|statically|Static by Default#}, but musl does:
$ zig build-exe --c-source hello.c --library c -target x86_64-linux-musl
$ ./hello
Hello world
$ ldd hello
not a dynamic executable
In this example, Zig built musl libc from source and then linked against it. The build of musl libc for x86_64-linux remains available thanks to the {#link|caching system|Build Artifact Caching#}, so any time this libc is needed again it will be available instantly.
This means that this functionality is available on any platform. Windows and macOS users can build Zig and C code, and link against libc, for any of the targets listed above. Similarly code can be cross compiled for other architectures:
$ zig build-exe --c-source hello.c --library c -target aarch64v8-linux-gnu
$ file hello
hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 2.0.0, with debug_info, not stripped
In some ways, Zig is a better C compiler than C compilers!
This functionality is more than bundling a cross-compilation toolchain along with Zig. For example, the total size of libc headers that Zig ships is 22MiB uncompressed. Meanwhile, the headers for musl libc + linux headers on x86_64 alone are 8MiB, and for glibc are 3.1MiB (glibc is missing the linux headers), yet Zig currently ships with 40 libcs. With a naive bundling that would be 444MiB. However, thanks to this process_headers tool that I made, and some good old manual labor, Zig binary tarballs remain roughly 30MiB total, despite supporting libc for all these targets, as well as compiler-rt, libunwind, and libcxx, and despite being a clang-compatible C compiler. For comparison, the Windows binary build of clang 8.0.0 itself from llvm.org is 132MiB.
Note that only the {#link|Tier 1 Support#} targets have been thoroughly tested. It is planned to add more libcs (including for Windows), and to add test coverage for building against all the libcs. Support for building the {#link|FreeBSD|FreeBSD Support#} libc startup files is the main feature needed to achieve {#link|Tier 1 Support#} for the target.
Thanks to Jay Weisskopf for helping with the glibc targets by removing an obsolete compat shim file.
{#header_close#} {#header_open|Libc Detection#}Although {#link|Zig ships with libc#} for some targets, it still supports building against the system-native libc.
0.4.0 introduces a new command zig libc
which prints
the various paths of libc files. It outputs them to stdout
in a simple text file format that it is capable of parsing.
You can use zig libc libc.txt
to validate a file.
Here's what it looks like on my NixOS laptop:
$ zig libc
# The directory that contains `stdlib.h`.
# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
include_dir=/nix/store/q2q1sg5sljia8sihhwcpbxir70yw33bw-glibc-2.27-dev/include
# The system-specific include directory. May be the same as `include_dir`.
# On Windows it's the directory that includes `vcruntime.h`.
# On POSIX it's the directory that includes `sys/errno.h`.
sys_include_dir=/nix/store/q2q1sg5sljia8sihhwcpbxir70yw33bw-glibc-2.27-dev/include
# The directory that contains `crt1.o`.
# On POSIX, can be found with `cc -print-file-name=crt1.o`.
# Not needed when targeting MacOS.
crt_dir=/nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib
# The directory that contains `vcruntime.lib`.
# Only needed when targeting MSVC on Windows.
msvc_lib_dir=
# The directory that contains `kernel32.lib`.
# Only needed when targeting MSVC on Windows.
kernel32_lib_dir=
And here's what it looks like on my Windows laptop:
> zig.exe libc
# The directory that contains `stdlib.h`.
# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
include_dir=C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17134.0\ucrt
# The system-specific include directory. May be the same as `include_dir`.
# On Windows it's the directory that includes `vcruntime.h`.
# On POSIX it's the directory that includes `sys/errno.h`.
sys_include_dir=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\lib\x64\\..\..\include
# The directory that contains `crt1.o`.
# On POSIX, can be found with `cc -print-file-name=crt1.o`.
# Not needed when targeting MacOS.
crt_dir=C:\Program Files (x86)\Windows Kits\10\\Lib\10.0.17134.0\ucrt\x64\
# The directory that contains `vcruntime.lib`.
# Only needed when targeting MSVC on Windows.
msvc_lib_dir=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\lib\x64\
# The directory that contains `kernel32.lib`.
# Only needed when targeting MSVC on Windows.
kernel32_lib_dir=C:\Program Files (x86)\Windows Kits\10\\Lib\10.0.17134.0\um\x64\
These arguments are gone:
--libc-lib-dir [path] directory where libc crt1.o resides --libc-static-lib-dir [path] directory where libc crtbegin.o resides --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides
Instead we have this argument:
--libc [file] Provide a file which specifies libc paths
This is used to pass a libc text file (which can be generated with
zig libc
). So it is easier to manage multiple cross compilation
environments.
When Zig must depend on the native libc installation, it first looks for
zig-cache/native_libc.txt
. If found, this file will be used. If this
file does not exist or has a parse error, Zig will perform native libc detection
and then overwrite this file. This can save time, because native libc detection can
be time consuming. For example it may need to invoke the system C compiler several
times to find out paths of things, or it may invoke some Windows COM API which is a bit
non-deterministic in terms of performance.
The --static
CLI option is removed and the -dynamic
option is added.
Instead of an explicit --static
flag, Zig makes things as static
as possible by default. Even zig build-lib
will now create a static
library by default, but -dynamic
can be used to choose a dynamic
library.
When targeting Linux, Zig now automatically links statically when not linking against
any shared libraries. It also disables Position Independent Code in this case, which
improves performance, especially with regards
to {#link|Thread-Local Variables#}. --enable-pic
and --disable-pic
can be used to override the default, but this
should be a rare use case.
Position Independent Code is also disabled by default for the freestanding OS target. When targeting Windows, Position Independent Code is always enabled.
It is proposed to rename these options to -fPIC
and -fno-PIC
to match C compilers.
For some use cases, it is known at compile-time that a given application or executable will never participate in multi-threading. For these use cases Zig has Single-Threaded Builds.
There is now a compile option --single-threaded
which has the following effects:
--single-threaded
. #1910exit_group
syscall when not single-threaded.The feature is exposed in the {#link|Zig Build System#} with {#syntax#}foo.single_threaded = true;{#endsyntax#}
{#header_close#} {#header_open|Zig Build System#}
When one invokes the zig build
command, this executes a user-defined
build script. This is called the zig build system. It received
a few improvements during this release cycle.
Notably, {#link|Build Artifact Caching#} is enabled by default.
This means that by default build artifacts are now output into the
zig-cache
directory. The output path is not predictable and if the build
script desires to run an executable, rather than hard coding a path and using
{#syntax#}builder.addCommand{#endsyntax#}, build scripts
must use {#syntax#}executable.run{#endsyntax#} API, or {#syntax#}addArtifactArg{#endsyntax#}.
An example of this can be found in the
tetris example.
{#syntax#}builder.addSystemCommand{#endsyntax#} is available to run commands that are not created by the build system itself. An example of this can be found in the Raspberry Pi OS example.
Another option build scripts have is to specify the output directory of an artifact with {#syntax#}artifact.setOutputDir{#endsyntax#}. This disables caching and makes {#syntax#}artifact.getOutputPath{#endsyntax#}, {#syntax#}artifact.getOutputLibPath{#endsyntax#}, and {#syntax#}artifact.getOutputHPath{#endsyntax#} available.
Finally, the best way to make the output path of an artifact predictable is to install it with the build system's install step. There are some ergonomics and defaults to improve with this strategy, which will be tackled during the next release cycle.
Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually.
--output
, --output-lib
, and --output-h
are removed.
Instead, use --output-dir
which defaults to the current working directory.
Or take advantage of --cache on
, which will print the main output
path to stdout, and the other artifacts will be in the same directory
with predictable file names. --disable-gen-h
is available when
one wants to prevent .h file generation.
@cImport is always independently cached now.
It always writes the generated Zig code to disk which makes debug
info and compile errors better. No more "TODO: remember C source
location to display here" #2015.
The --verbose-cimport
command no longer dumps Zig AST to stderr; instead
it prints the file paths of the generated .zig files for inspection. In addition to
this improved behavior, the common case of {#syntax#}@cImport{#endsyntax#} with all the
C header files unchanged is now fast due to being cached, yet still correct if any of
the C files change.
In addition, these improvements were made:
os_self_exe_path
to determine exe path not argv[0]
--static
. #2027zig build --help
more friendly. (#2194)--disable-gen-h
to control that behaviour. However,
setting {#syntax#}lib.disable_gen_h = true{#endsyntax#} in a typical build.zig
didn't append
the option to arguments. This commit fixes it and adds a convenient setDisableGenH
setter.
Zig comes with a robust caching system. When compiling Zig code, Zig knows all the files that
it depends on, and when compiling C code, Zig uses -MV -MD -MF
parameters to
Clang and then parses the generated .d file.
The other component of this is the "compiler id" concept:
$ zig id
Cxb7A-sAjt6VDq35pHZj3ACcwiSFqcCndt0NJkdQQlZVKolwm-QKnce1KEMUTqPr
This is the hash of the compiler binary itself, plus all the dynamic libraries it depends on,
directly or indirectly. That means if you fix a bug in memcpy
in the system libc,
Zig will detect this change and the value of zig id
will be different.
However, the value is quickly computed because it also participates in the caching system.
Here is a "manifest file" in the caching system for zig id
:
4850313<PHONE_NUMBER> 416647968 cOOP0xpsfiYfuMJCS3V_fLKdNmxFxLih_UACAUqwynGp1Y616NJ2lHL0hOpWOp_o /home/andy/dev/zig/build/zig
3077799 1 0 bBgfkt9ZSVN_HgBbzwHhzKmQxpssdDYq_HcbEkdu7KDcUhanATUER2_5l_U__9DE /nix/store/5dphwv1xs46n0qbhynny2lbhmx4xh1fc-zlib-1.2.11/lib/libz.so.1
1165671 1 0 jSVrSQyNkPFoz0Z6GesezdVP1ZBRpHL2UbbX7HbNEprcU4aBuIyG9z6bAOvvPZr0 /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/librt.so.1
1165626 1 0 scJm8rYLhDLp_SDXmbvdlcj9fEWQadEm_kHUBJn2oGnht3pSh2MNzsUJZjR1wwa1 /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/libdl.so.2
1165664 1 0 pGDNQn5x_j1NAWzjh4AOUP8OKyJj1KSPd4SJYzRVbTTp7TRb4IQpDs7ZAU3muqfz /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/libpthread.so.0
1165631 1 0 4tmxoKlbVwB42gYxT7B3CKIBXpbGdb_vuqfYiXlOZdyngmFJdQ7DBZxWqZKSO0Ss /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/libm.so.6
3077645 1 0 dxe6qw_yMCi8Bp7ocrVcl2XMdRlKfa0S3ATqbxsEMISRQdQ1dyxTEE1uDbv0R54z /nix/store/sf0wnp30savqz9ljn6fsrn8f63w5v0za-gcc-7.4.0-lib/lib/libstdc++.so.6
1165630 1 0 5boikua2jQubswAtj8MICJzjmGNUxTZrNreQm_DmtspgRsXULyCkyUUMYcNFamII /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/libgcc_s.so.1
1165616 1 0 qiXB510da3ryfL7LcPUvL2EQgY2tIwszLRvgQdDrQtnWVl4zA1Nfpq4SDpIz3IYW /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/libc.so.6
1165607 1 0 MpHwajxu3h0TtsHViKMAmHHeGMbi9IuDLlybX6PpqT66Xfa1h2GAT3XFIX19dEz- /nix/store/fivq0nbggp4y8mhy3ixprqd7qyn1hy2j-glibc-2.27/lib/ld-linux-x86-64.so.2
The fields are, respectively:
This same system is used for build artifact caching. For example, here is the manifest file
for hello world in Zig (when built with --cache on
):
5505089<PHONE_NUMBER> 204467480 rcnRrxBgZSiWki_XN9XKlQ2yfWkM6KLYhUWprzniEBtjgmeUSmtlv5mAguA4l2Q1 /home/andy/dev/zig/example/hello_world/hello.zig
4850617<PHONE_NUMBER> 0 GXP-IfocPj934vVJYrccBKIVoOcWULaUtkBoR-iHnEKEIoXtdchyuQi8tk8FTncS /home/andy/dev/zig/build/lib/zig/std/std.zig
5114024<PHONE_NUMBER> 0 6u-vFMcHH_FcfkAyqCcoYXAfF2TLMCkoP86Q3Ykecmage7_E4ObRsfP52-YXDHH6 /home/andy/dev/zig/build/lib/zig/std/special/panic.zig
4850617<PHONE_NUMBER> 0 GXP-IfocPj934vVJYrccBKIVoOcWULaUtkBoR-iHnEKEIoXtdchyuQi8tk8FTncS /home/andy/dev/zig/build/lib/zig/std/std.zig
4850277<PHONE_NUMBER> 0 9S5aQg0ORbkQnvDCVeW2aNPSeCu993I4iO3JoGrif4py7zBS4si4mCaeHHuo9TEn /home/andy/dev/zig/build/lib/zig/std/debug.zig
4849956<PHONE_NUMBER> 0 8c76uDlKxK5jZ1L0Uup4Lu0y1NlU5-KrUCKFyZnzoi7Hv3dDByN8pvujTjxjaf0m /home/andy/dev/zig/build/lib/zig/std/os.zig
4850678<PHONE_NUMBER> 0 wFvlet_2y9YT6NlFrsqybubwMafHFCIZqq4AxLlcUGuTSZ7VjI8kGmM-3VKPrhkt /home/andy/dev/zig/build/lib/zig/std/io.zig
5112957<PHONE_NUMBER> 0 f29y95JhSfGVwEFrutPnquGPPuvvtOLu6_vUUgGbaqn-9uulgFvBnyPU8Zp_sH7r /home/andy/dev/zig/build/lib/zig/std/os/file.zig
5113386<PHONE_NUMBER> 0 Mb9m-jj_wRe6yt-TFko9wUGNToAA-IAbVfmR2TYZyPjKP3D87df6BGALjai5uKr2 /home/andy/dev/zig/build/lib/zig/std/os/windows/util.zig
5113248<PHONE_NUMBER> 0 F1infSSAdOgbOWl3y2FdUiB-6xrpTaeqUJ5xt_F9IZOeBvvTSLNpkGEg8mrYMcli /home/andy/dev/zig/build/lib/zig/std/os/linux.zig
5113251<PHONE_NUMBER> 0 LAlDVvl1TX-3-SB3MOBBjxuEk2Ms8SpkcYBLXnJONgZuo7aV9OYfXLfih9bfGyBS /home/andy/dev/zig/build/lib/zig/std/os/linux/errno.zig
5113278<PHONE_NUMBER> 0 TpIIt3DNczfgMKjhDA5mx-4JgoGd7SIV9lXK8GQs9Bix4EmPiL7VlV1oQVwv4gkO /home/andy/dev/zig/build/lib/zig/std/os/linux/x86_64.zig
4849832<PHONE_NUMBER> 0 AszHJ9beyMCotgQx4vwYWMBUcRd1dBspsou64fATNYXsSqwB5zAiqVEokfpV5xkF /home/andy/dev/zig/build/lib/zig/std/fmt.zig
4850680<PHONE_NUMBER> 0 Polq06O1t-jJ0SobBVqLaQrJVXaKzH4lQj6Na8NRN3Y5N0pZ2I4W2rpwL816MSz- /home/andy/dev/zig/build/lib/zig/std/io/seekable_stream.zig
4850605<PHONE_NUMBER> 0 Al_VWoytLHeozYOvM69cCR2Dw1HGYdJc2lDGQDXYoiJy1VuD6GWLIQhxSJuf3Oza /home/andy/dev/zig/build/lib/zig/std/array_list.zig
4877695<PHONE_NUMBER> 0 ouDIQ9yX5LXanXk6mc2ypFP-oy2zEt7uLLlPDVUFEfx4AKmeFP1cJWI7YSjYAVt9 /home/andy/dev/zig/build/lib/zig/std/mem.zig
4850649<PHONE_NUMBER> 0 rVa_7s1plylcGIUAHEt3eGG8XwSJAEOQzuIaYcnq0KHnb1IoGWUEXUGIW7QHH7fi /home/andy/dev/zig/build/lib/zig/std/elf.zig
4849844<PHONE_NUMBER> 0 58Tg88pYb1sgK8SI5_65Gy7lgCqaJmsW2NV-Hi4FeXOK8e2f2T1PofNfdUDgbYit /home/andy/dev/zig/build/lib/zig/std/math.zig
4850647<PHONE_NUMBER> 0 9-R2p6FQ_7UIjQMt3N-chgeh-_e_o29Gr2Pybfh2PurmRYT9mIIwsdW9rs6kEJR8 /home/andy/dev/zig/build/lib/zig/std/dwarf.zig
5113295<PHONE_NUMBER> 0 6oc1oIiWQJ1OIZGh5KFPtul93GCeAaLFx2VTICI3JMt-Ubnj-vjXvBBclnoo5UQ6 /home/andy/dev/zig/build/lib/zig/std/os/path.zig
4850677<PHONE_NUMBER> 0 qom60op_QDptmhKO6SIlpm48SlVybcFOT0gHCjncJvtZhM6uUNqZZ2Q0WV5AsmRP /home/andy/dev/zig/build/lib/zig/std/heap.zig
4850683<PHONE_NUMBER> 0 6t3PH8KaWwsz2MElBWZezzyZyeRS-Ttq6k2pJWwRK__NvVQ2hZSu1gk4jA7oDT_Y /home/andy/dev/zig/build/lib/zig/std/linked_list.zig
4850685<PHONE_NUMBER> 0 EsROc7EV9MKNd74wRR9tYFhMGs4CL4eqYSPvJVzKTzSoXABBfxVoQwO3N_VivhNG /home/andy/dev/zig/build/lib/zig/std/macho.zig
4850663<PHONE_NUMBER> 0 oWDxArJXQLKaeAqd-Uf52hiAjktfqEhJA4XIdlBKCeKOxbYZosChXsfReGM0azCQ /home/andy/dev/zig/build/lib/zig/std/hash_map.zig
4877700<PHONE_NUMBER> 0 0SY3kFjpRYGQ1eVmh4UHluGBDFA9LcwANsSlEZLKfBO6hWxoZWcowtXk1SJvSALu /home/andy/dev/zig/build/lib/zig/std/pdb.zig
4850628<PHONE_NUMBER> 0 QEww1cNolzNrXqhOMV8uMTXRXQmbekZ7nyUaEqj35x6ZjO8BRVzqvYxQeSmW8c_5 /home/andy/dev/zig/build/lib/zig/std/coff.zig
4877702<PHONE_NUMBER> 0 9cFnTGm01DAKqMZim8dzEXoPyN8w3R8UAer53ycBv2PFgg-pM6AsNd6hDf0jlseT /home/andy/dev/zig/build/lib/zig/std/rand.zig
5113402<PHONE_NUMBER> 0 m2d1Awh2J4qJuWpBI5sEZJyszBZB2VIZlHvVpXZlt9Vz9JdjXvMN2Cig4ohevME_ /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig
4877697<PHONE_NUMBER> 0 y2XL97U7jZ9PY4d5TVVZmBzYQc5wrCE_j_utDeU8zfLp5W6iLdFEf_HLbG4-W9Mf /home/andy/dev/zig/build/lib/zig/std/mutex.zig
4877707<PHONE_NUMBER> 0 jd03IjTqKqI-sTTbTTL63EjXX2xp9vPInAn4fA0rRis3TeXGgWnP-44_8N0OTRPP /home/andy/dev/zig/build/lib/zig/std/spinlock.zig
The way the cache checking works, is that it calls fstat
on all the files in the
manifest. For each file, if the inodes and mtimes from the manifest match the results from
fstat
, then the hash is trusted to be up-to-date for that particular file.
Any files with outdated hashes, have their contents hashed, and the manifest file updated
with the updated hashes. Finally, all the hashes are hashed together, and that final hash
is used as the directory name within zig-cache
that Zig looks for previously
created build artifacts.
Because Zig uses -MD -MF
args to clang when doing
{#syntax#}@cImport{#endsyntax#}, Zig has a complete list of files that the C code read from,
which Zig adds to the cache. So even when using {#syntax#}@cImport{#endsyntax#},
Zig's caching system remains perfect. This is a proof of concept
for the mechanism that the {#link|self-hosted compiler|Self-Hosted Compiler Status#}
will use to watch and rebuild files.
There is one really fascinating problem to solve when relying on file modification times to determine whether a file's contents have changed. Some file systems, such as macOS's HFS+, do not support nanosecond precision; only seconds. However even nanosecond precision exhibits the problem for very fast systems.
Imagine that a file was modified, and then immediately after, added to the cache. When added to the manifest, the current time and the file's mtime will be the same. If the file is modified again quickly, and then the cache checked, it will still be the same instant in time; the modification to the file did not change the mtime.
There is a beautiful solution to this problem, which is to disqualify a file from being cached if the current time, truncated to the file system time granularity, matches the mtime:
// If the wall clock time, rounded to the same precision as the
// mtime, is equal to the mtime, then we cannot rely on this mtime
// yet. We will instead save an mtime value that indicates the hash
// must be unconditionally computed.
static bool is_problematic_timestamp(const OsTimeStamp *fs_clock) {
OsTimeStamp wall_clock = os_timestamp_calendar();
// First make all the least significant zero bits in the fs_clock, also zero bits in the wall clock.
if (fs_clock->nsec == 0) {
wall_clock.nsec = 0;
if (fs_clock->sec == 0) {
wall_clock.sec = 0;
} else {
wall_clock.sec &= (-1ull) << ctzll(fs_clock->sec);
}
} else {
wall_clock.nsec &= (-1ull) << ctzll(fs_clock->nsec);
}
return wall_clock.nsec == fs_clock->nsec && wall_clock.sec == fs_clock->sec;
}
What's beautiful about this is that it generalizes to any granularity. If a file system had a 1 day mtime granularity, then this would mean any files modified within 1 day would have to have their contents hashed, but files older than that could have their hashes trusted. If a file system always wrote 0 for the mtime, Zig would never trust it.
Thanks to apenwarr's insightful blog post about build system caching for inspiration.
The caching system is disabled by default for the command line interface, except for zig test
. zig test
does respect --output-dir
however, which disables caching.
The default caching behavior can be overridden with --cache [on|off]
.
The {#link|Zig Build System#} enables caching by default.
Caching is always enabled, using the global cache directory, when building libc and compiler-rt. This saves a considerable amount of accumulated time, since they must be available for every compilation.
{#header_close#} {#header_close#} {#header_open|Valgrind Compatibility#}
Zig's compatibility with Valgrind has improved. Notably,
Valgrind 3.14 fixes
a bug where Zig programs' debug symbols
would not be detected. Because of this, the --no-rosegment
command line option is removed from Zig. It was only meant to be a temporary workaround.
Thanks to daurnimator for adding a valgrind module to the standard library. This allows Zig code to easily make Valgrind client requests.
In addition to userland API, Zig integrates more tightly with Valgrind. For example, one thing that Zig does in Debug builds is write {#syntax#}0xaa{#endsyntax#} bytes to {#syntax#}undefined{#endsyntax#} variables:
{#code_begin|exe|undef#} const std = @import("std"); pub fn main() void { var array: [10]u8 = undefined; std.debug.warn("array: {x}\n", array); } {#code_end#}Valgrind has detection for branching on undefined values, but if Zig was writing {#syntax#}0xaa{#endsyntax#} values to uninitialized variables, Valgrind would not know that this is supposed to be an undefined canary. It would see the values as defined. However thanks to integrated Valgrind client requests with the Zig language, Valgrind knows what's going on:
{#code_begin|exe|undef#} const std = @import("std"); pub fn main() void { var x: i32 = 1234; std.debug.warn("x = {}\n", x); x = undefined; if (x > 10) { std.debug.warn("greater than 10\n"); } } {#code_end#}When run in valgrind:
==16484== Conditional jump or move depends on uninitialised value(s)
==16484== at 0x224B6C: main (undef.zig:7)
==16484== by 0x22455A: posixCallMainAndExit (bootstrap.zig:86)
==16484== by 0x224350: _start (bootstrap.zig:43)
This is a debugging tool available in Zig that is not available in C - setting things to {#syntax#}undefined{#endsyntax#} so that Valgrind can catch it if you accidentally use it.
Language integration with Valgrind is enabled by default in
Debug mode, and disabled by default in other
modes. The feature can be force enabled or force disabled with
--enable-valgrind
and --disable-valgrind
, respectively.
Also available is {#syntax#}@import("builtin").valgrind_support{#endsyntax#} which is a
{#syntax#}comptime{#endsyntax#} {#syntax#}bool{#endsyntax#} available for code to
find out whether the programmer wants the executable to have Valgrind integration.
It's always disabled for compiler_rt and libc/builtin.
The cost of this feature is a few assembly instructions with each assignment to {#syntax#}undefined{#endsyntax#}. Only support for Linux, macOS, Solaris, and MinGW on x86_64 is currently implemented.
{#header_close#} {#header_open|zig fmt#}zig fmt
is a tool to format your Zig code to a canonical style.
It's implemented in Zig and it's been available as a
{#link|self-hosted compiler|Self-Hosted Compiler Status#} subcommand for a while,
but the self-hosted compiler is not done yet and it's not what's available on
the download page.
Zig 0.4.0 ships with zig fmt
capabilities. Under the hood, it uses
zig run
and the {#link|Build Artifact Caching#} system, to lazily build
zig fmt
from source, and then run it.
That means even the stage1 C++ Zig compiler is a sort of hybrid - part C++, and part Zig.
Several editors have zig fmt
integration available, such as the
vim plugin that I use.
I believe the VSCode plugin does as well.
There is now has a --check
flag, which does everything
except modify file contents. That is, it lists non-conforming files on stdout,
and then exits with an error if the list is non-empty. #1558 #1555
Other improvements during this release cycle:
this
as a keyword since it was
removed in 0.3.0.There is also a discussion about whether or not to align struct fields, which has some interesting arguments on either side.
{#header_close#} {#header_open|C Translation Status#}I have come up with a plan to migrate translate-c to userland:
This will allow us to move thousands of lines of C++ to Zig, and to only have to maintain one implementation of C translation rather than two. This same strategy could be used for other pieces of the Zig project, such as the {#link|package manager|Package Manager Status#}.
I started this effort with a proof of concept, but there is still a long way to go before this is done.
In addition the following improvements were made:
--verbose-cimport
prints clang commandassert
macro from glibc.Jimmi lead this effort. Starting with solving the return type ambiguity (#1628), he then moved on to create zig-spec, update the grammar section of the language reference, and update the stage1 parser to conform.
Thanks to his efforts, Zig syntax now has a formal grammar specification and three independent implementations, despite the fact that the syntax is not fully stablized.
{#header_close#} {#header_open|Documentation#}The language reference manual. now has a light theme by default, but respects the user's light/dark preference via the prefers-color-scheme media query. Most browsers don't support this yet, so we just have to wait patiently for the future to arrive.
Instead of a side bar index, the index is inline with the rest of the content. This is simpler and more friendly to all user agents, and means we don't need the media query for mobile devices. It also makes back-references work, so now headers link to the table of contents and the table of contents links to headers.
Both of these things apply to this release notes document as well as the language reference manual.
There is still no HTML documentation available for the Zig Standard Library. See the {#link|Roadmap#} for more details.
The master branch language reference manual is now automatically updated on master branch commits that pass all tests on all platforms.
In addition to the above, the following changes were made to the documentation:
section
keyword to {#syntax#}linksection{#endsyntax#}. #1152@minValue
,@maxValue
; add {#syntax#}std.math.minInt{#endsyntax#} and {#syntax#}std.math.maxInt{#endsyntax#}. #1466 #1476All numbers with comptime known values now implicitly cast to all number types. If the value does not fit, a compile error is emitted.
{#code_begin|test|comptime_ints#} const std = @import("std"); const assert = std.debug.assert; test "implicit cast large integer to smaller with comptime value" { const x: u64 = 255; const y: u8 = x; assert(y == 255); } {#code_end#} {#header_close#} {#header_open|Vectors and SIMD#}Zig 0.4.0 ships with a new Vector type. This feature is brand new and not well documented yet. Here are some example tests:
{#code_begin|test|vectors#} const std = @import("std"); const mem = std.mem; const expect = std.testing.expect; test "vector wrap operators" { const S = struct { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{<PHONE_NUMBER>, -2, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1,<PHONE_NUMBER>, 3, 4 }; expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ -2147483648,<PHONE_NUMBER>, 33, 44 })); expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{<PHONE_NUMBER>,<PHONE_NUMBER>, 27, 36 })); expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{<PHONE_NUMBER>, 2, 90, 160 })); var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 }; expect(mem.eql(i32, ([4]i32)(-%z), [4]i32{ -1, -2, -3, -2147483648 })); } }; S.doTheTest(); comptime S.doTheTest(); } test "vector int operators" { const S = struct { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; expect(mem.eql(i32, ([4]i32)(v + x), [4]i32{ 11, 22, 33, 44 })); expect(mem.eql(i32, ([4]i32)(v - x), [4]i32{ 9, 18, 27, 36 })); expect(mem.eql(i32, ([4]i32)(v * x), [4]i32{ 10, 40, 90, 160 })); expect(mem.eql(i32, ([4]i32)(-v), [4]i32{ -10, -20, -30, -40 })); } }; S.doTheTest(); comptime S.doTheTest(); } test "vector float operators" { const S = struct { fn doTheTest() void { var v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 }; var x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 }; expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 })); expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 })); expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 })); expect(mem.eql(f32, ([4]f32)(-x), [4]f32{ -1, -2, -3, -4 })); } }; S.doTheTest(); comptime S.doTheTest(); } test "vector bit operators" { const S = struct { fn doTheTest() void { var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 }; var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 }; expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); } }; S.doTheTest(); comptime S.doTheTest(); } {#code_end#}Note that Zig of course supports vectors at {#syntax#}comptime{#endsyntax#} and likewise all the safety features of arithmetic operators are available for vectors as well.
Vectors provide a way to do Single Instruction Multiple Data in a portable and efficient way. It's much easier for the optimizer to break vectors into scalars than it is to turn scalars into vectors. Even in debug builds which have safety checks, vector operations provide more data throughput than scalar operations.
Thanks to Jimmi Holst Christensen for many contributions to vector support.
To follow progress on vectors and SIMD in Zig, watch issue #903.
{#header_close#} {#header_open|comptime memory reinterpretation#}Zig's {#syntax#}comptime{#endsyntax#} facilities are improved to support reinterpreting memory, as long as the types in question have guaranteed in-memory representation.
{#code_begin|test|bitcast#} const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; test "@bitCast extern structs at runtime and comptime" { const Full = extern struct { number: u16, }; const TwoHalves = extern struct { half1: u8, half2: u8, }; const S = struct { fn doTheTest() void { var full = Full{ .number = 0x1234 }; var two_halves = @bitCast(TwoHalves, full); switch (builtin.endian) { builtin.Endian.Big => { expect(two_halves.half1 == 0x12); expect(two_halves.half2 == 0x34); }, builtin.Endian.Little => { expect(two_halves.half1 == 0x34); expect(two_halves.half2 == 0x12); }, } } }; S.doTheTest(); comptime S.doTheTest(); } test "reinterpret bytes of an array into an extern struct" { testReinterpretBytesAsExternStruct(); comptime testReinterpretBytesAsExternStruct(); } fn testReinterpretBytesAsExternStruct() void { var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; const S = extern struct { a: u8, b: u16, c: u8, }; var ptr = @ptrCast(*const S, &bytes); var val = ptr.c; expect(val == 5); } {#code_end#}These examples work because {#syntax#}extern struct{#endsyntax#} and {#syntax#}packed struct{#endsyntax#} have guaranteed in-memory layout.
In addition, as long as the memory is never accessed, pointers with hard coded addresses and pointer arithmetic are supported at {#syntax#}comptime{#endsyntax#}:
{#code_begin|test|comptime_ptrs#} const std = @import("std"); const expect = std.testing.expect; test "C pointer comparison and arithmetic" { const S = struct { fn doTheTest() void { var one: usize = 1; var ptr1: [*c]u32 = 0; var ptr2 = ptr1 + 10; expect(ptr1 == 0); expect(ptr1 >= 0); expect(ptr1 <= 0); expect(ptr1 < 1); expect(ptr1 < one); expect(1 > ptr1); expect(one > ptr1); expect(ptr1 < ptr2); expect(ptr2 > ptr1); expect(ptr2 >= 40); expect(ptr2 == 40); expect(ptr2 <= 40); ptr2 -= 10; expect(ptr1 == ptr2); } }; S.doTheTest(); comptime S.doTheTest(); } {#code_end#} {#header_close#} {#header_open|Thread-Local Variables#}A variable may be specified to be a thread-local variable using the {#syntax#}threadlocal{#endsyntax#} keyword:
{#code_begin|test|tls#} const std = @import("std"); const assert = std.debug.assert; threadlocal var x: i32 = 1234; test "thread local storage" { const thread1 = try std.os.spawnThread({}, testTls); const thread2 = try std.os.spawnThread({}, testTls); testTls({}); thread1.wait(); thread2.wait(); } fn testTls(context: void) void { assert(x == 1234); x += 1; assert(x == 1235); } {#code_end#}For {#link|Single-Threaded Builds#}, all thread local variables are treated as Global Variables.
Thread local variables may not be {#syntax#}const{#endsyntax#}.
Note that thread local variables have better performance for non- position independent code, which is one reason for {#link|Static by Default#}.
Thanks to Rich Felker from the musl libc project, who gave me this crucial information, when I was implementing thread local storage for static builds:
to satisfy the abi, your init code has to write the same value to that memory location as the value passed to the [arch_prctl] syscall{#header_open|Avoid Creating Unnecessary Global Constants#}
This deletes some legacy cruft, and produces leaner object files. Example:
{#code_begin|syntax#} var x: i32 = 1234; export fn entry() i32 { return x; } {#code_end#}This produced:
@x = internal unnamed_addr global i32 1234, align 4
@0 = internal unnamed_addr constant i32* @x, align 8
and @0 was never even used. After Zig 0.4.0, @0 is not produced.
This fixes a bug: Zig was creating invalid LLVM IR when one of these globals that shouldn't exist takes the address of a thread local variable. In {#link|LLVM 8#}, it would produce a linker error. But probably after my bug report is solved it will be caught by the IR verifier.
Thanks to Rui Ueyama and George Rimar who helped me troubleshoot this problem when I filed an LLVM bug report.
{#header_close#} {#header_close#} {#header_open|C Pointers#}One of the use cases of Zig is to beat C at its own game, and this means being a better language for using C libraries than C is. It's a tall order to fulfill, and it was compromised by Zig's pointer reform. An unfortunate side effect of having more type safety in pointer types was that C's very unsafe pointer types became awkward to use. It is ambiguous whether pointers should be {#link|translated|C Translation Status#} as single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
C Pointers are a compromise so that Zig code can utilize translated header files directly.
This type is to be avoided whenever possible. The only valid reason for using a C pointer is in auto-generated code from translating C code.
{#syntax#}[*c]T{#endsyntax#} - C pointer.
It's planned to support `if`, `orelse`, `null`, and `.?` for C pointers.
While C pointers themselves have all the footguns associated with, well, C pointers, there is safety when converting to Zig pointers:
{#code_begin|test_err|causes pointer to be null#} test "cast null C pointer to Zig pointer" { var c_ptr: [*c]i32 = 0; var zig_ptr: *i32 = c_ptr; } {#code_end#} {#header_close#} {#header_open|Removal of the Namespace Type#}
In Zig 0.3.0, {#syntax#}@typeOf(@import("builtin")){#endsyntax#} is (import)
,
which was a special "namespace" type. In Zig 0.4.0,
{#syntax#}@typeOf(@import("builtin")){#endsyntax#} is {#syntax#}type{#endsyntax#}.
The special "namespace" type is removed; instead all files are structs with no fields.
This makes the language smaller and simpler, and makes imported files easier to inspect with reflection, since they are structs.
With this change, struct types get fully qualified names and function symbol names
become fully qualified. This means that when using zig test
it's no longer
necessary to manually namespace test names as they will be automatically namespaced.
There is a new compile error for importing a file outside the package path.
The new CLI option --main-pkg-path
can be used to choose
a different root package directory besides the one inferred from the
root source file. The corresponding {#link|Zig Build System#} API is
{#syntax#}artifact.setMainPkgPath(path){#endsyntax#}.
Zig has a new type to make dealing with enums more attractive. It can be thought of as the {#syntax#}enum{#endsyntax#} equivalent of {#syntax#}comptime_int{#endsyntax#}. The {#syntax#}enum{#endsyntax#} equivalent of a number literal.
{#code_begin|exe|enum-lit#} const std = @import("std"); pub fn main() void { print(1234, .hex); print(1234, .normal); } fn print(x: i32, mode: enum { normal, hex }) void { switch (mode) { .normal => std.debug.warn("{}\n", x), .hex => std.debug.warn("0x{x}\n", x), } } {#code_end#}Here you can see an anonymous {#syntax#}enum{#endsyntax#} was used rather than an opaque {#syntax#}bool{#endsyntax#} parameter. The idea here is to make it so easy to have meaningful values, that programmers will want to use them, even if they're feeling lazy.
The ergonomics of this feature feel great. Here's tgschultz updating some of the standard library API to use anonymous enum literals.
Note that this feature is checked by the compiler. It's completely safe:
{#code_begin|test_err|has no field#} const std = @import("std"); test "invalid enum literal" { print(1234, .hex); print(1234, .invalid); } fn print(x: i32, mode: enum { normal, hex }) void { switch (mode) { .normal => std.debug.warn("{}\n", x), .hex => std.debug.warn("0x{x}\n", x), } } {#code_end#} {#header_close#} {#header_close#} {#header_open|Standard Library API Changes#}EBUSY
when trying to open for writing a tty fd that is already opened with screen.Previously, {#syntax#}std.debug.assert{#endsyntax#} would @panic in test builds, if the assertion failed. Now, it's always {#syntax#}unreachable{#endsyntax#}.
This makes release mode test builds more accurately test the actual code that will be run.
However this requires tests to call {#syntax#}std.testing.expect{#endsyntax#} rather than {#syntax#}std.debug.assert{#endsyntax#} to make sure output is correct.
Here is the explanation of when to use either one, copied from the assert doc comments:
Inside a test block, it is best to use the {#syntax#}std.testing{#endsyntax#} module rather than assert, because assert may not detect a test failure in ReleaseFast and ReleaseSmall modes. Outside of a test block, assert is the correct function to use.
See #1304.
{#header_close#} {#header_open|std.debug.captureStackTrace#}Zig code can use {#syntax#}std.debug.captureStackTrace{#endsyntax#} at any time for debugging purposes:
{#code_begin|exe|stack-traces#} const std = @import("std"); const builtin = @import("builtin"); var address_buffer: [8]usize = undefined; var trace1 = builtin.StackTrace{ .instruction_addresses = address_buffer[0..4], .index = 0, }; var trace2 = builtin.StackTrace{ .instruction_addresses = address_buffer[4..], .index = 0, }; pub fn main() void { foo(); bar(); std.debug.warn("first one:\n"); std.debug.dumpStackTrace(trace1); std.debug.warn("\n\nsecond one:\n"); std.debug.dumpStackTrace(trace2); } fn foo() void { std.debug.captureStackTrace(null, &trace1); } fn bar() void { std.debug.captureStackTrace(null, &trace2); } {#code_end#}This feature is used in the GeneralPurposeDebugAllocator project for helping detect and diagnose memory issues.
{#header_close#} {#header_open|Allocator interface#}Zig 0.4.0 brings breaking changes to the {#syntax#}std.mem.Allocator{#endsyntax#} interface and API.
Before, allocator implementations had to provide {#syntax#}allocFn{#endsyntax#}, {#syntax#}reallocFn{#endsyntax#}, and {#syntax#}freeFn{#endsyntax#}.
Now, they must provide only {#syntax#}reallocFn{#endsyntax#} and {#syntax#}shrinkFn{#endsyntax#}. Reallocating from a zero length slice is allocation, and shrinking to a zero length slice is freeing.
When the new memory size is less than or equal to the previous allocation size, {#syntax#}reallocFn{#endsyntax#} now has the option to return {#syntax#}error.OutOfMemory{#endsyntax#} to indicate that the allocator would not be able to take advantage of the new size.
For more details see #1306.
I have reproduced the documentation comments here:
{#code_begin|syntax#} pub const Allocator = struct { pub const Error = error{OutOfMemory}; /// Realloc is used to modify the size or alignment of an existing allocation, /// as well as to provide the allocator with an opportunity to move an allocation /// to a better location. /// When the size/alignment is greater than the previous allocation, this function /// returns `error.OutOfMemory` when the requested new allocation could not be granted. /// When the size/alignment is less than or equal to the previous allocation, /// this function returns `error.OutOfMemory` when the allocator decides the client /// would be better off keeping the extra alignment/size. Clients will call /// `shrinkFn` when they require the allocator to track a new alignment/size, /// and so this function should only return success when the allocator considers /// the reallocation desirable from the allocator's perspective. /// As an example, `std.ArrayList` tracks a "capacity", and therefore can handle /// reallocation failure, even when `new_n` <= `old_mem.len`. A `FixedBufferAllocator` /// would always return `error.OutOfMemory` for `reallocFn` when the size/alignment /// is less than or equal to the old allocation, because it cannot reclaim the memory, /// and thus the `std.ArrayList` would be better off retaining its capacity. /// When `reallocFn` returns, /// `return_value[0..min(old_mem.len, new_byte_count)]` must be the same /// as `old_mem` was when `reallocFn` is called. The bytes of /// `return_value[old_mem.len..]` have undefined values. /// The returned slice must have its pointer aligned at least to `new_alignment` bytes. reallocFn: fn ( self: *Allocator, /// Guaranteed to be the same as what was returned from most recent call to /// `reallocFn` or `shrinkFn`. /// If `old_mem.len == 0` then this is a new allocation and `new_byte_count` /// is guaranteed to be >= 1. old_mem: []u8, /// If `old_mem.len == 0` then this is `undefined`, otherwise: /// Guaranteed to be the same as what was returned from most recent call to /// `reallocFn` or `shrinkFn`. /// Guaranteed to be >= 1. /// Guaranteed to be a power of 2. old_alignment: u29, /// If `new_byte_count` is 0 then this is a free and it is guaranteed that /// `old_mem.len != 0`. new_byte_count: usize, /// Guaranteed to be >= 1. /// Guaranteed to be a power of 2. /// Returned slice's pointer must have this alignment. new_alignment: u29, ) Error![]u8, /// This function deallocates memory. It must succeed. shrinkFn: fn ( self: *Allocator, /// Guaranteed to be the same as what was returned from most recent call to /// `reallocFn` or `shrinkFn`. old_mem: []u8, /// Guaranteed to be the same as what was returned from most recent call to /// `reallocFn` or `shrinkFn`. old_alignment: u29, /// Guaranteed to be less than or equal to `old_mem.len`. new_byte_count: usize, /// If `new_byte_count == 0` then this is `undefined`, otherwise: /// Guaranteed to be less than or equal to `old_alignment`. new_alignment: u29, ) []u8, }; {#code_end#}This allows allocators and data structures to "negotiate" with each other. For example, here is {#syntax#}std.ArrayList.shrink{#endsyntax#}:
{#code_begin|syntax#} pub fn shrink(self: *Self, new_len: usize) void { assert(new_len <= self.len); self.len = new_len; self.items = self.allocator.realloc(self.items, new_len) catch |e| switch (e) { error.OutOfMemory => return, // no problem, capacity is still correct then. }; } {#code_end#} {#header_close#} {#header_close#} {#header_open|Please Welcome Antoine Vugliano to the Core Zig Team#}I am pleased to announce our newest Zig team member, Antoine Vugliano.
He has shown continued dedication and discipline in his contributions to the Zig programming language project. The quality of his work speaks for itself.
I look forward to working with Antoine as we continue to push Zig toward 1.0.0 and beyond.
{#header_close#} {#header_open|Syntax Highlighting on GitHub#}Thanks to Jeff Fowler for creating sublime-zig-language and for creating the pull request to GitHub to add support for Zig.
Finally, GitHub decided that Zig is popular enough to gain official recognition.
As a fun last step, Marc Tiehuis marked third-party dependencies as vendored, so that we can have this pretty language bar on GitHub:
Now you can discover Zig projects on GitHub via their "trending" web page.
{#header_close#} {#header_open|Miscellaneous Improvements#}ar
.
#1493 #54
posix_spawn
rather than
fork
and execv
. The logic is simplified and the memory usage
is more deterministic.
-target [name]
instead of --target-*
args.
This matches clang's command line interface.zig targets
only shows available targets. #438zig targets
but note they are {#link|Tier 4 Support#}.__modti3
to compiler-rt. #1290Function type mismatches now have an error note which explains in more detail why the function types were incompatible:
{#code_begin|test_err|cannot cast into#} fn do_the_thing(func: fn (arg: i32) void) void {} fn bar(arg: bool) void {} test "fn types" { do_the_thing(bar); } {#code_end#} {#header_close#} {#header_close#} {#header_open|Bug Fixes#}handle_is_ptr
. #991 #1934bigint_append_buf
. All current usages had base 10
and a limb length of 2, hence why we weren't hitting this error in practice.--
double-hyphen is now used to end further zig processing
of command line options. All arguments after --
will be passed
on to the executable. eg. --help
will be passed on:
zig run foo.zig -- --help
Zig has known bugs.
The first release that will ship with no known bugs will be 1.0.0.
{#header_close#} {#header_close#} {#header_open|Roadmap#}Here is the roadmap from 0.3.0 release notes:
I am sad to report that this list was too ambitious for one release cycle, and while there has been considerable progress, none of these items are complete. And so the roadmap for 0.4.0 is the same.
{#header_open|Type-Based Alias Analysis Status#}It's no longer planned for Zig to have Type Based Alias Analysis. However, there are some open research topics on potentially outlawing all kinds of aliasing unless explicitly declared. Subscribe to #1108 for more details.
For now, Zig has a {#link|well-defined memory model|comptime memory reinterpretation#}, and aliasing is always allowed. Note, however, that not all types have a guaranteed in-memory layout.
{#header_close#} {#header_open|macOS/Mach-O Linker Status#}Linking macOS/COFF files is still in a sad state. The Mach-O code in LLD, Zig's linker, has been barely maintained for several years now. Zig has a fork of LLD in its source tree with a hacky patch to fix linking "Hello World" on macOS.
It's now planned for the Zig project to have its own linker. This is in part due to the lack of Mach-O maintenance, and in part because LLD has no plans to do incremental linking - a feature that I foresee to be necessary to achieve the performance we want to have for large projects in the self-hosted compiler.
For now the self-hosted compiler uses --system-linker-hack
to be able to link successfully, which is a compromise of Zig's promise that it can build
on any target, for any target.
There is also a workaround in the linker phase of Zig for compiler-rt.a and builtin.a. I had to make them object files rather than archive files to avoid crashing LLD.
{#header_close#} {#header_open|Self-Hosted Compiler Status#}There has been no progress on the self-hosted compiler in this release cycle. Progress is blocked on the volume of core language changes still happening, as well as no-copy semantics, and {#link|Reworking Coroutines|Coroutine Status#}.
{#header_close#} {#header_open|Package Manager Status#}The package manager will be one of the focus areas of the 0.5.0 release cycle. It depends on networking, which depends on {#link|Reworking Coroutines|Coroutine Status#}, which depends on no-copy semantics.
{#header_close#} {#header_open|Coroutine Status#}There is no progress on coroutines in this release cycle. In fact there has been anti-progress.
Zig 0.4.0 introduces a memory leak to all coroutines. There is an issue where a coroutine calls the function and it frees its own stack frame, but then the return value of {#syntax#}shrinkFn{#endsyntax#} is a slice, which is implemented as an sret struct. Writing to the return pointer causes invalid memory write. We could work around it by having a global helper function which has a void return type and calling that instead. But instead this hack will suffice until I rework coroutines to be non-allocating. Basically coroutines are not supported right now until they are reworked as in #1194.
Reworking coroutines is to be a major focus of 0.5.0 as it is blocking networking, the {#link|Package Manager|Package Manager Status#}, and the {#link|Self-Hosted Compiler|Self-Hosted Compiler Status#}.
{#header_close#} {#header_open|Accepted Proposals#}Here is a small selection of interesting proposals that have been accepted, to give you an idea of the upcoming changes to Zig.
Full list of accepted proposals
{#header_close#} {#header_close#} {#header_open|Active External Projects Using Zig#}Special thanks to those who donate monthly. Thanks to you, Zig is not driven by the needs of a business; instead it exists solely to serve the open source community.


Our bot is already available on Telegram
Check out what Faang Bot can do!
Top internship postings from FAANG and other tech companies!
Top relevant new grad jobs postings delivered!
Daily updates on new job opportunities!
Direct links to application pages from all over the Internet!