-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.nim
133 lines (116 loc) · 3.93 KB
/
build.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import std/[os, osproc, strformat, strutils]
type
BuildKind = enum
bkDebug = ""
bkRelease = "release"
bkDanger = "danger"
Mm = enum
mmOrc = "orc"
mmArc = "arc"
mmRefc = "refc"
Opt = enum
optSpeed = "speed"
optSize = "size"
LinkingKind = enum
lkDynamic
lkStaticMuslGcc
lkStaticMuslClang
lkStaticMuslZig
CompileOptions = object
buildKind: BuildKind
flto: bool
strip: bool
mm: Mm
opt: Opt
linkingKind: LinkingKind
func init(T: typedesc[CompileOptions],
buildKind = bkDebug,
flto = false,
strip = false,
mm = mmOrc,
opt = optSpeed,
linkingKind = lkDynamic): T =
T(
buildKind: buildKind,
flto: flto,
strip: strip,
mm: mm,
opt: opt,
linkingKind: linkingKind,
)
when defined(linux):
proc warn(msg: string) =
stderr.write "Warning: "
stderr.writeLine msg
proc getCompilationOptions: seq[CompileOptions] =
result = @[
CompileOptions.init(),
CompileOptions.init(bkRelease),
CompileOptions.init(bkRelease, flto = true),
CompileOptions.init(bkRelease, flto = true, strip = true),
CompileOptions.init(bkRelease, flto = true, strip = true, opt = optSize),
]
when defined(linux):
if findExe("musl-gcc").len > 0:
result.add CompileOptions.init(bkRelease, flto = true, strip = true,
opt = optSize,
linkingKind = lkStaticMuslGcc)
else:
warn("musl-gcc not found")
if findExe("musl-clang").len > 0:
result.add CompileOptions.init(bkRelease, flto = true, strip = true,
opt = optSize,
linkingKind = lkStaticMuslClang)
else:
warn("musl-clang not found")
if findExe("zig").len > 0:
result.add CompileOptions.init(bkRelease, opt = optSize,
linkingKind = lkStaticMuslZig)
else:
warn("zig not found")
func `$`(c: CompileOptions): string =
result = if c.buildKind == bkDebug: "" else: &"-d:{c.buildKind}"
if c.flto:
result.add " --passC:-flto --passL:-flto"
if c.strip:
result.add " --passL:-s"
if c.mm != mmOrc:
result.add &" --mm:{c.mm}"
if c.opt == optSize:
result.add &" --opt:{c.opt}"
case c.linkingKind
of lkDynamic:
discard
of lkStaticMuslGcc:
result.add " --cc:gcc --gcc.exe:musl-gcc --gcc.linkerexe:musl-gcc --passL:-static"
of lkStaticMuslClang:
result.add " --cc:clang --clang.exe:musl-clang --clang.linkerexe:musl-clang --passL:-static"
of lkStaticMuslZig:
const pathZigcc = currentSourcePath().parentDir() / "zigcc"
result.add " --panics:on -d:useMalloc --os:any -d:posix -d:noSignalHandler" &
&" --cc=clang --clang.exe='{pathZigcc}' --clang.linkerexe='{pathZigcc}'" &
" --passC:'-flto -target x86_64-linux-musl'" &
" --passL:'-flto -target x86_64-linux-musl'"
proc execAndCheck(cmd: string) =
## Runs `cmd`, and raises an exception if the exit code is non-zero.
let (output, exitCode) = execCmdEx(cmd)
if exitCode != 0:
stderr.writeLine output
raise newException(OSError, "Command returned non-zero exit code: " & cmd)
proc main =
const filename = "hello"
const binaryPath = when defined(windows): &"{filename}.exe" else: filename
let options = getCompilationOptions()
for opts in options:
let s = $opts
let cmd = fmt"nim c --skipParentCfg --skipProjCfg {s} {filename}"
execAndCheck(cmd)
# strip the zigcc binary, where `--passL:-s` doesn't work.
if opts.linkingKind == lkStaticMuslZig:
execAndCheck(&"strip -s -R .comment {filename}")
let binarySize = getFileSize(binaryPath).float / 1024
echo &"{binarySize:>5.1f} KiB {s}"
let cmdRunHello = when defined(windows): binaryPath else: &"./{binaryPath}"
doAssert execCmdEx(cmdRunHello) == ("Hello, World!\n", 0)
when isMainModule:
main()