News for hackers. Stuff that matters.
Re:Show HN: Tiny 1k Rust binary on Windows by acqq on Tuesday December 01, 2020 @09:05AM (#25265191)
It's very easy and fast to try: using 0.7.0+51d7c14ce from https://ziglang.org/download/ and:

   const std = @import("std");

   pub fn main() void {
      std.debug.print("Hello, world!\n", .{});
   }
----------

zig build-exe hello.zig -O ReleaseSmall --strip --single-threaded -target x86_64-windows

Resulting hello.exe is 3072 bytes. From these 2560 are zero bytes. The only system calls from the resulting binary are to ExitProcess, GetLastError and WriteFile from KERNEL32.dll Additionally, changing the release optimizations:

zig build-exe hello.zig -O ReleaseFast --single-threaded --strip -target x86_64-windows

produces hello.exe of 2560 bytes, 1849 from which are zeroes.

Note all: winter_blue has right to mention Zig. It's about what's provided out of the box in that new language and the provided optimizations are really effective.

Edit: asking mcountryman to explain: "the compiled rust exe has 480 non-zero bytes" -- I think you mean not just "compiled" but "hand-optimized writing hundreds of lines of the rust source code and not using standard library"? https://github.com/mcountryman/min-sized-rust-windows/blob/m... https://github.com/mcountryman/min-sized-rust-windows/blob/m...

Edit2: Please note that zig doesn't eventually link to printf and libc there, but links and resolves the std calls from the source to the calls to KERNEL32.dll.

Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Tuesday December 01, 2020 @10:43AM (#25266114)
Ah, yeah, I wasn't trying to shrug off the usefulness of zig, sorry. I think when it comes to compile size zig does it a bit better due to it's smaller std although, when compiling rust with just a link to libc and a printf call I believe you get an exe ~2048b when optimizing for size so I'm not certain how well that scales.

The 100 line hack I used was to noop out the `.idata` section which link.exe refused to merge/shrink, that only saved me 1Kb in the end.

Looking at the section info of the zig exe it looks like there is some black magic going on with it's alignment so I may have to dig deeper to see what zig is doing here. Also thank you both for pointing zig out, I haven't heard of it until now and it may come in handy for something else I'm planning on making :)

Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Tuesday December 01, 2020 @04:05PM (#25269885)
@Edit2 I saw that, and that's pretty cool in regards to how the zig std is a wrapper rather than a rewrite. Although, if we were optimizing for size in this case it might be more optimal to have only one entry in the import table :D
Re:Show HN: Tiny 1k Rust binary on Windows by acqq on Tuesday December 01, 2020 @05:26PM (#25270863)
Maybe "zig std is a wrapper rather than a rewrite" was the slip and what's written is the opposite of the idea? I wouldn't call zig's std "a wrapper" in this case where it implements the functionality without the C standard library? Had it called something in the C library, then I'd call it a wrapper.
Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Wednesday December 02, 2020 @08:30AM (#25276150)
Yeah my choice of words wasn't great. It seams as if the zig std acts as a macro rather than a wrapper. That could just be the aggressive optimization though
Re:Show HN: Tiny 1k Rust binary on Windows by acqq on Wednesday December 02, 2020 @09:36AM (#25276674)
What name would you use after seeing the implementation of the functions called?

std/debug.zig:

    pub fn print(comptime fmt: []const u8, args: anytype) void {
        const held = stderr_mutex.acquire();
        defer held.release();
        const stderr = io.getStdErr().writer();
        nosuspend stderr.print(fmt, args) catch return;
    }

io/writer.zig:

    pub fn print(self: Self, comptime format: []const u8, args: anytype) Error!void {
        return std.fmt.format(self, format, args);
    } 
std/fmt.zig:

    pub fn format(
        writer: anytype,
        comptime fmt: []const u8,
        args: anytype,
    ) !void {
       ...
It's all based on the language features and the actual implementations of zig's standard library code, and at least I don't see anything "wrapped" there, and nothing what C++, C or asm programmers understand as "a macro".
Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Wednesday December 02, 2020 @03:51PM (#25281443)
Very well optimized inlined functions?

I didn't actually check the zig std source. I was referring to what I was seeing in radare2 :)

Re:Show HN: Tiny 1k Rust binary on Windows by acqq on Wednesday December 02, 2020 @04:16PM (#25281768)
In zig there's a concept of "comptime" -- note that fmt parameter is marked as such. It's more than just inlining.

https://ziglang.org/documentation/master/#comptime

See an example calling firstNPrimes. "When we compile this program, Zig generates the constants with the answer pre-computed." "Note that we did not have to do anything special with the syntax of these functions. For example, we could call the sum function as is with a slice of numbers whose length and values were only known at run-time."

Then see "Case Study: printf in Zig"

Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Wednesday December 02, 2020 @06:31PM (#25283266)
I'm a little short on time so I didn't read through all of it but, comptime generics sounds similar to how rust compiles generics and comptime parameters are similar to const fns although zig appears to have more control over what is deamed "compile time".
Re:Show HN: Tiny 1k Rust binary on Windows by mcountryman on Tuesday December 01, 2020 @09:36AM (#25265493)
Just for fun, the compiled rust exe has 480 non-zero bytes, the zig exe had 512 bytes.