Important Notice: this service will be discontinued by the end of 2024 because for multiple years now, Plume is no longer under active/continuous development. Sadly each time there was hope, active development came to a stop again. Please consider using our Writefreely instance instead.

The Size of A Greeting - Followup

Hello World

This is a followup post that the main post links to, just to declutter things. Go back

The Makefile

SHELL=/usr/bin/bash #nicer `time` builtin

all: compile

.PHONY: compile
compile: ada ats c cxx carp cleanlang crystal d fortran go haskell nim ocaml odin pascal rust sml swift terra v zig # Fails to compile: koka red

.PHONY: ada
ada: gnat.exe
gnat.exe: hello.adb
	@echo ===============[$@]===================
	time gnatmake -Os -flto -o $@ $<
	@rm *.ali *.o

.PHONY: ats
ats: patsopt.exe
# ATS2
patsopt.exe: hello.dats
	@echo ===============[$@]===================
	time ATSCCOMP='-flto -Os' patscc -cleanaft -o $@ $<

.PHONY: c 
c: gcc.exe tcc.exe clang.exe
gcc.exe: hello.c
	@echo ===============[$@]===================
	time gcc -Os -flto -o $@ $<
tcc.exe: hello.c
	@echo ===============[$@]===================
	time tcc -Os -flto -o $@ $<
clang.exe: hello.c
	@echo ===============[$@]===================
	time clang -Os -flto -o $@ $<

.PHONY: cxx 
cxx: g++.exe clang++.exe
g++.exe: hello.cxx
	@echo ===============[$@]===================
	time g++ -Os -flto -o $@ $<
clang++.exe: hello.cxx
	@echo ===============[$@]===================
	time clang++ -Os -flto -o $@ $<

.PHONY: carp 
carp: carp.exe
carp.exe: hello.carp
	@echo ===============[$@]===================
	time carp -b --optimize --no-profile $<
	@mv out/Untitled $@
	@rm -rf out/

.PHONY: cleanlang
cleanlang: clm-gcmark.exe clm-gccopy.exe clm.exe
clm-gcmark.exe: hello.icl
	@echo ===============[$@]===================
	time clm -b -nt -gcm hello
	@mv a.out $@
	@rm -rf "Clean System Files/"
clm-gccopy.exe: hello.icl
	@echo ===============[$@]===================
	time clm -b -nt -gcc hello
	@mv a.out $@
	@rm -rf "Clean System Files/"
clm.exe: hello.icl
	@echo ===============[$@]===================
	time clm -b -nt hello
	@mv a.out $@
	@rm -rf "Clean System Files/"

.PHONY: crystal 
crystal: crystal.exe
crystal.exe: hello.cr
	@echo ===============[$@]===================
	time crystal build --release --no-debug -o $@ $<

.PHONY: d 
d: dmd.exe ldmd2.exe gdc.exe
dmd.exe: hello.d
	@echo ===============[$@]===================
	time dmd -O -release -of=$@ $<
	@rm *.o
ldmd2.exe: hello.d
	@echo ===============[$@]===================
	time ldmd2 -O -release -of=$@ $<
	@rm *.o
gdc.exe: hello.d
	@echo ===============[$@]===================
	time gdc -Os -flto -o $@ $<

.PHONY: fortran 
fortran: gfortran.exe
# Fortran90
gfortran.exe: hello.f90
	@echo ===============[$@]===================
	time gfortran -Os -flto -o $@ $<

.PHONY: go 
go: go.exe
go.exe: hello.go
	@echo ===============[$@]===================
	time go build -o $@ $< #IDK if go has any actual size opt flags

.PHONY: haskell 
haskell: ghc.exe
ghc.exe: hello.hs
	@echo ===============[$@]===================
	time ghc --make -O -optc-Os -no-keep-{hi,o}-files -o $@ $<

# OOM
.PHONY: koka 
koka: koka.exe
koka.exe: hello.kk
	@echo ===============[$@]===================
	time koka -c -O2 --ccopts='-Os -flto' --outname=$@ $<
	@mv out/*/*release/$@ .
	@rm -rf out/

.PHONY: nim 
nim: nim.exe
nim.exe: hello.nim
	@echo ===============[$@]===================
	time nim c --opt:size --app:console -o:$@ $<

.PHONY: ocaml
ocaml: ocamlopt.exe
ocamlopt.exe: hello.ml
	@echo ===============[$@]===================
	time ocamlopt -compact -ccopt '-Os -flto' -o $@ $<
	@rm *.cm? *.o

.PHONY: odin 
odin: odin.exe
odin.exe: hello.odin
	@echo ===============[$@]===================
	time odin build $< -opt:1 -out:$@ #opt:1 is best for size

.PHONY: pascal 
pascal: fpc.exe
# Free Pascal
fpc.exe: hello.p
	@echo ===============[$@]===================
	fpc -Os -Ow -o$@ $< #fpc prints timing info
	@rm *.o

# Red doesn't even recognize its own compilation options
.PHONY: red
red: red.exe
red.exe: hello.red
	@echo ===============[$@]===================
	time red -r -o $@ $<

.PHONY: rust 
rust: rustc.exe # mrustc.exe
rustc.exe: hello.rs
	@echo ===============[$@]===================
	time rustc -C debuginfo=0 -C opt-level=z -C code-model=small -C lto=on \
		-o $@ $<
mrustc.exe: hello.rs
	@echo ===============[$@]===================
	time mrustc -O -o $@ $< # Doesn't work; no std crate available

.PHONY: sml 
sml: mlton.exe
mlton.exe: hello.sml
	@echo ===============[$@]===================
	time mlton -cc-opt '-Os -flto' -output $@ $<

.PHONY: swift 
swift: swiftc.exe
swiftc.exe: hello.swift
	@echo ===============[$@]===================
	time swiftc -gnone -Osize -Xcc -Os -Xcc -flto -o $@ $<

.PHONY: terra 
terra: terra.exe
terra.exe: hello.t
	@echo ===============[$@]===================
	time echo $@ | terra $< #flags in the file itself

.PHONY: v 
v: v-native.exe v-transpiled.exe
v-native.exe: hello.v
	@echo ===============[$@]===================
	time v $< -b x64 -prod -o $@
v-transpiled.exe: hello.v
	@echo ===============[$@]===================
	time v $< -b c -prod -o $@

.PHONY: zig 
zig: zig.exe
zig.exe: hello.zig
	@echo ===============[$@]===================
	time zig build-exe $< -O ReleaseSmall -femit-bin=$@
	@rm -rf zig-cache/

.PHONY: wc
wc: compile
	@echo "unstripped: "
	@wc -c *.exe |sort -nr
	@echo
	@echo "stripped: "
	@strip -s *.exe
	@wc -c *.exe |sort -nr

.PHONY: run
run: compile
	@for exe in *.exe; do echo "$$exe:"; strace -c ./$$exe; echo; done |& less

.PHONY: clean
clean:
	-rm *.exe

The Implementations

Ada: hello.adb

with Ada.Text_IO;

procedure Hello_World is
   use Ada.Text_IO;
begin
   Put_line ("Hello World");
end Hello_World;

C: hello.c

#include <stdio.h>

int main() {
	printf("Hello World\n");
	return 0;
}

Carp: hello.carp

(use IO)

(defn main []
  (println "Hello World"))

Crystal: hello.cr

puts "Hello World"

C++: hello.cxx

#include <iostream>

int main() {
   std::cout << "Hello World" << std::endl;
}

D: hello.d

import std.stdio;

void main() {
	writeln("Hello World");
}

ATS2: hello.dats

implement main0 () = println! "Hello World"

Fortran: hello.f90

program helloworld
print '(a)', 'Hello World'
end program helloworld

Go: hello.go

package main

import "fmt"

func main() {
	fmt.Println("Hello World")
}

Haskell: hello.hs

main = putStrLn "Hello World"

Clean: hello.icl

module hello

Start :: {#Char}
Start = "Hello World\n"

Koka: hello.kk

fun main () : console () {
    println("Hello World")
}

OCaml: hello.ml

let _ = print_endline "Hello World"

Nim: hello.nim

echo "Hello World"

Odin: hello.odin

package main

import "core:fmt"

main :: proc() {
  fmt.println("Hello World");
}

Free Pascal: hello.p

program HelloWorld(output);
begin
        writeln('Hello World');
end.

Red: hello.red

Red [Title: "Greeting"]
print "Hello World"

Rust: hello.rs

fn main() {
    println!("Hello World");
}

StandardML: hello.sml

val _ = print "Hello World\n"

Swift: hello.swift

print("Hello World")

Terra: hello.t

stdio = terralib.includec("stdio.h")
hello = terralib.constant(rawstring,'Hello World')

terra main ()
   stdio.puts(hello)
end

terralib.saveobj(io.read(),'executable',{main=main},{'-Os','-flto'})

V: hello.v

println("Hello World")

Zig: hello.zig

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello World\n", .{});
}

Linked Libs

carp.exe:
	linux-vdso.so
	libm.so
	libc.so
	ld-linux-x86-64.so
clang.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
clang++.exe:
	linux-vdso.so
	libstdc++.so
	libm.so
	libgcc_s.so
	libc.so
	ld-linux-x86-64.so
clm.exe:
	linux-vdso.so
	libm.so
	libc.so
	ld-linux-x86-64.so
clm-gccopy.exe:
	linux-vdso.so
	libm.so
	libc.so
	ld-linux-x86-64.so
clm-gcmark.exe:
	linux-vdso.so
	libm.so
	libc.so
	ld-linux-x86-64.so
crystal.exe:
	linux-vdso.so
	libpcre.so
	libm.so
	libgc.so
	libpthread.so
	libevent-2.1.so
	librt.so
	libdl.so
	libgcc_s.so
	libc.so
	ld-linux-x86-64.so
dmd.exe:
	linux-vdso.so
	libpthread.so
	libm.so
	librt.so
	libdl.so
	libgcc_s.so
	libc.so
	ld-linux-x86-64.so
fpc.exe:
	not a dynamic executable
gcc.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
gdc.exe:
	linux-vdso.so
	libgcc_s.so
	libm.so
	libpthread.so
	libdl.so
	libz.so
	libc.so
	ld-linux-x86-64.so
g++.exe:
	linux-vdso.so
	libstdc++.so
	libm.so
	libgcc_s.so
	libc.so
	ld-linux-x86-64.so
gfortran.exe:
	linux-vdso.so
	libgfortran.so
	libm.so
	libgcc_s.so
	libquadmath.so
	libc.so
	ld-linux-x86-64.so
ghc.exe:
	linux-vdso.so
	libgmp.so
	libc.so
	libm.so
	librt.so
	libdl.so
	libffi.so
	libpthread.so
	ld-linux-x86-64.so
gnat.exe:
	linux-vdso.so
	libdl.so
	libc.so
	ld-linux-x86-64.so
go.exe:
	not a dynamic executable
ldmd2.exe:
	linux-vdso.so
	librt.so
	libdl.so
	libpthread.so
	libm.so
	libgcc_s.so
	libc.so
	ld-linux-x86-64.so
mlton.exe:
	linux-vdso.so
	libm.so
	libgmp.so
	libc.so
	ld-linux-x86-64.so
nim.exe:
	linux-vdso.so
	libdl.so
	libc.so
	ld-linux-x86-64.so
ocamlopt.exe:
	linux-vdso.so
	libm.so
	libdl.so
	libc.so
	ld-linux-x86-64.so
odin.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
	libm.so
patsopt.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
rustc.exe:
	linux-vdso.so
	libgcc_s.so
	libpthread.so
	libdl.so
	libc.so
	ld-linux-x86-64.so
swiftc.exe:
	linux-vdso.so
	libswiftCore.so
	libc.so
	libpthread.so
	libdl.so
	libicui18nswift.so
	libicuucswift.so
	libicudataswift.so
	libstdc++.so
	libm.so
	libgcc_s.so
	ld-linux-x86-64.so
tcc.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
terra.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
v-native.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
v-transpiled.exe:
	linux-vdso.so
	libc.so
	ld-linux-x86-64.so
zig.exe:
	not a dynamic executable