blob: 2c949f4c175ab296689123747a4e526c95e25fe2 [file] [log] [blame]
swissChili0fc3f262021-08-09 22:05:17 -07001# Rewrite of JMK in TCL
2
3variable jmk_name {}
4variable jmk_target {}
swissChilif3d65762022-07-03 22:34:54 -07005variable jmk_clean_libs {}
6variable jmk_phony_libs {}
7variable jmk_lib_paths
8variable jmk_lib_targets
9
swissChili9b46c902022-07-10 15:48:46 -070010variable jmk_sourced
11
swissChili0fc3f262021-08-09 22:05:17 -070012variable cflags {}
13variable asmflags {}
swissChilif3d65762022-07-03 22:34:54 -070014variable ldflags {}
swissChili0fc3f262021-08-09 22:05:17 -070015
swissChili14d0b842023-01-01 02:22:44 -050016variable asm nasm
swissChilif3d65762022-07-03 22:34:54 -070017variable cc gcc
18variable ld ld
19
20variable objs {}
swissChili0fc3f262021-08-09 22:05:17 -070021
swissChili35558852022-07-02 18:15:45 -070022# variable options
23
24variable src \$^
25variable first_src \$<
26variable target \$@
swissChili0fc3f262021-08-09 22:05:17 -070027
28proc init {name {target {DEFAULT_TARGET}}} {
29 if {$target eq {DEFAULT_TARGET}} {
30 set target $name
31 }
32
33 global jmk_name
34 global jmk_target
35
36 set jmk_name $name
37 set jmk_target $target
swissChili35558852022-07-02 18:15:45 -070038
39 puts {MAKEFILE_DEPTH ?= 1}
40
41 rule all $target {}
swissChilif3d65762022-07-03 22:34:54 -070042
swissChili0fc3f262021-08-09 22:05:17 -070043}
44
45proc preset {p} {
46 ::preset::$p
47}
48
49proc presets {args} {
50 foreach arg $args {
51 preset $arg
52 }
53}
54
55proc cflag {arg} {
56 global cflags
57 set cflags "$cflags $arg"
58}
59
60proc cflags {args} {
61 foreach arg $args {
62 cflag $arg
63 }
64}
65
66proc asmflag {arg} {
67 global asmflags
68 set asmflags "$asmflags $arg"
69}
70
71proc asmflags {args} {
72 foreach arg $args {
73 asmflag $arg
74 }
75}
76
swissChilif3d65762022-07-03 22:34:54 -070077proc ldflag {arg} {
78 global ldflags
79 set ldflags "$ldflags $arg"
80}
81
82proc ldflags {args} {
83 foreach arg $args {
84 ldflag $arg
85 }
86}
87
swissChili0fc3f262021-08-09 22:05:17 -070088proc option {name val} {
89 global options
90 if {![info exists options($name)]} {
91 set options($name) $val
92 }
93}
94
swissChili35558852022-07-02 18:15:45 -070095proc log {category message} {
swissChilif3d65762022-07-03 22:34:54 -070096 puts "\t@printf ' \\e\[1;34m%8s\\e\[m %s\\n' '$category' '$message' > /dev/stderr"
swissChili35558852022-07-02 18:15:45 -070097}
98
swissChili9b46c902022-07-10 15:48:46 -070099proc jmk_log {message} {
100 puts stderr $message
101}
102
103proc jmk_error {message} {
104 puts stderr "\e[31mError\e[0m $message"
105 exit 1
106}
107
swissChili35558852022-07-02 18:15:45 -0700108proc cc {command} {
109 puts "\t@$::cc $command $::cflags"
110}
111
112proc asm {command} {
113 puts "\t@$::asm $command $::asmflags"
114}
115
116proc shell {command} {
117 puts "\t@$command"
118}
119
swissChilif3d65762022-07-03 22:34:54 -0700120proc make {command} {
121 shell "\$(MAKE) --no-print-directory MAKEFILE_DEPTH=\$\$((\$(MAKEFILE_DEPTH)+1)) $command"
122}
123
swissChili35558852022-07-02 18:15:45 -0700124proc rule {target deps does} {
125 puts ""
126 puts "$target: $deps"
swissChilif3d65762022-07-03 22:34:54 -0700127 uplevel 1 $does
swissChili35558852022-07-02 18:15:45 -0700128}
129
130proc type {type} {
131 ::type::$type
132}
133
swissChilif3d65762022-07-03 22:34:54 -0700134proc objs {args} {
135 foreach obj $args {
136 set ::objs "$::objs $obj"
137 }
138}
139
swissChili35558852022-07-02 18:15:45 -0700140proc srcs {args} {
141 puts ""
swissChili35558852022-07-02 18:15:45 -0700142
143 foreach src $args {
swissChili9b46c902022-07-10 15:48:46 -0700144 set src [file join [pwd] $src]
swissChili35558852022-07-02 18:15:45 -0700145 variable obj [regsub -- {(.+)\.\w+} $src {\1.o}]
swissChilif3d65762022-07-03 22:34:54 -0700146 set ::objs "$::objs $obj"
swissChili0db97752022-07-29 21:09:16 -0700147
swissChilie4229a22023-01-01 15:59:53 -0500148 set relpath [exec sh -c "realpath --relative-to '$::jmk_makefile_dir' '$src'"]
149
swissChili0db97752022-07-29 21:09:16 -0700150 if {[string match *.c $src]} {
151 variable cc $::cc
152 if {[string match *distcc* $cc]} {
153 variable cc [regsub -- {.*distcc +(.+)$} $cc {\1}]
154 }
155
156 if {[file exists $src]} {
157 puts [exec sh -c "$cc $src -MM -MT $obj $::cflags"]
158 } else {
159 rule $obj $src {}
160 }
161
swissChilie4229a22023-01-01 15:59:53 -0500162 log CC $relpath
swissChili0db97752022-07-29 21:09:16 -0700163 cc "-c $::first_src -o $::target"
164 puts ""
swissChilie4229a22023-01-01 15:59:53 -0500165 } elseif {[string match *.s $src]} {
166 log ASM $relpath
167 rule $obj $src {
168 asm "$::asmflags $::first_src -o $::target"
169 }
swissChili0db97752022-07-29 21:09:16 -0700170 }
swissChilif3d65762022-07-03 22:34:54 -0700171 }
172}
173
174proc depends {name path {target DEFAULT_TARGET}} {
175 if {$target eq {DEFAULT_TARGET}} {
176 variable target "lib${name}.a"
swissChili35558852022-07-02 18:15:45 -0700177 }
178
swissChilif3d65762022-07-03 22:34:54 -0700179 set ::jmk_clean_libs "$::jmk_clean_libs $path"
180 set ::jmk_lib_paths($name) $path
181 set ::jmk_lib_target($name) $target
182 set ::jmk_phony_libs "$::jmk_phony_libs $path"
183
184 rule "$path/$target" {} {
185 log "MAKE\[\$(MAKEFILE_DEPTH)\]" "Entering $name"
186 make "-C $path $target"
187 log "MAKE\[\$(MAKEFILE_DEPTH)\]" "Leaving $name"
188 }
189}
190
191proc lib {name} {
192 return "$::jmk_lib_paths($name)/$::jmk_lib_target($name)"
swissChili35558852022-07-02 18:15:45 -0700193}
194
195namespace eval type {
196 proc executable {} {
197 global jmk_target
198
swissChilif3d65762022-07-03 22:34:54 -0700199 rule $jmk_target $::objs {
swissChili35558852022-07-02 18:15:45 -0700200 log LD $::target
201 cc "-o $::target $::src"
202 }
203
204 helpers
205 }
206
swissChilif3d65762022-07-03 22:34:54 -0700207proc custom_link {} {
208 global jmk_target
209
210 rule $jmk_target $::objs {
211 log LD $::target
212 shell "$::ld $::ldflags -o $::target $::src"
213 }
214
215 helpers
216}
217
swissChili35558852022-07-02 18:15:45 -0700218proc helpers {} {
swissChili0db97752022-07-29 21:09:16 -0700219 # rule .c.o {} {
220 # log CC $::first_src
221 # cc "-c $::first_src -o $::target"
222 # }
swissChili35558852022-07-02 18:15:45 -0700223
swissChili35558852022-07-02 18:15:45 -0700224 rule clean {} {
swissChilif3d65762022-07-03 22:34:54 -0700225 shell "rm -f **/*.o **/*.a *.so $::jmk_target $::objs"
226
227 foreach lib $::jmk_clean_libs {
228 make "-C $lib clean"
229 }
swissChili35558852022-07-02 18:15:45 -0700230 }
swissChilif3d65762022-07-03 22:34:54 -0700231}
swissChili35558852022-07-02 18:15:45 -0700232}
233
swissChili0fc3f262021-08-09 22:05:17 -0700234namespace eval preset {
swissChili35558852022-07-02 18:15:45 -0700235 proc freestanding {} {
236 cflags -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding
237 }
238
239 proc optimize {} {
240 cflags -O2
241 }
242
swissChili0fc3f262021-08-09 22:05:17 -0700243 proc debug {} {
244 cflag -g
swissChili0fc3f262021-08-09 22:05:17 -0700245 }
246
247 proc warn {} {
swissChilie4229a22023-01-01 15:59:53 -0500248 cflags -Wall
swissChili0fc3f262021-08-09 22:05:17 -0700249 }
250
swissChili56cf8172022-07-30 18:47:48 -0700251 proc 32 {} {
252 cflag -m32
253 asmflag -felf32
254 }
255
swissChili0fc3f262021-08-09 22:05:17 -0700256 proc nasm {} {
swissChili56cf8172022-07-30 18:47:48 -0700257 set ::asm nasm
258 asmflag -Fdwarf
swissChili0fc3f262021-08-09 22:05:17 -0700259 }
260}
swissChili9b46c902022-07-10 15:48:46 -0700261
262proc jmk_source {path} {
263 variable dir [pwd]
264
265 if {![file exists $path]} {
swissChili14d0b842023-01-01 02:22:44 -0500266 jmk_error "jmk_source: $path doesn't exist"
swissChili9b46c902022-07-10 15:48:46 -0700267 }
268
swissChili14d0b842023-01-01 02:22:44 -0500269 lappend ::jmk_sourced "$path"
swissChili9b46c902022-07-10 15:48:46 -0700270
271 cd [file dirname $path]
272 uplevel 1 source [file tail $path]
273 cd $dir
274}
275
276proc jmk_finalize {} {
swissChili14d0b842023-01-01 02:22:44 -0500277 rule Makefile "Jmk2 $::jmk_sourced" {
278 log JMK2 ""
279 shell "cd $::jmk_build_dir && $::jmk_build_cmd"
280 }
swissChili9b46c902022-07-10 15:48:46 -0700281}