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
|
package main
import (
"bytes"
"fmt"
"io/fs"
"os"
"path"
"strings"
)
var (
outputExe = "game"
compilerExe = "g++"
compilerOptions = []string{
"-m64",
"-fno-strict-aliasing",
"-pedantic",
"-Wall",
"-Wextra",
"-Wno-unused-parameter",
"-Wno-format-truncation",
"-std=c++11",
"-DOS_LINUX=1",
"-DARCH_X64=1",
}
linkerOptions = []string{
"-Wl,-t",
}
)
func main() {
if len(os.Args) < 2 {
fmt.Println("USAGE: makefile.exe SRCDIR")
os.Exit(1)
}
sourceDir := os.Args[1]
buildDir := path.Join(path.Dir(sourceDir), "build")
type Object struct{ obj, src string }
objectFiles := []Object{}
headerFiles := []string{}
fs.WalkDir(os.DirFS(sourceDir), ".",
func(rel string, d fs.DirEntry, err error) error {
if err == nil && !d.IsDir() {
ext := path.Ext(rel)
switch ext {
case ".cpp", ".cxx", ".cc", ".c":
src := rel
obj := rel[:len(src)-len(ext)] + ".obj"
objectFiles = append(objectFiles, Object{obj, src})
case ".hpp", ".hxx", ".hh", ".h":
hdr := rel
headerFiles = append(headerFiles, hdr)
}
}
return nil
})
output := bytes.Buffer{}
// VARIABLES
fmt.Fprintf(&output, "SRCDIR = %v\n", sourceDir)
fmt.Fprintf(&output, "BUILDDIR = %v\n", buildDir)
fmt.Fprintf(&output, "OUTPUTEXE = %v\n", outputExe)
fmt.Fprint(&output, "\n")
fmt.Fprintf(&output, "CC = %v\n", compilerExe)
fmt.Fprintf(&output, "CFLAGS = %v\n", strings.Join(compilerOptions, " "))
fmt.Fprintf(&output, "LFLAGS = %v\n", strings.Join(linkerOptions, " "))
fmt.Fprint(&output, "\n")
// DEBUG SWITCH
fmt.Fprint(&output, "DEBUG ?= 0\n")
fmt.Fprint(&output, "ifneq ($(DEBUG), 0)\n")
fmt.Fprint(&output, "\tCFLAGS += -g -O0\n")
fmt.Fprint(&output, "else\n")
fmt.Fprint(&output, "\tCFLAGS += -O2\n")
fmt.Fprint(&output, "endif\n")
// HEADERS
fmt.Fprint(&output, "HEADERS =")
for _, header := range headerFiles {
fmt.Fprintf(&output, " $(SRCDIR)/%v", header)
}
fmt.Fprint(&output, "\n\n")
// EXECUTABLE
fmt.Fprint(&output, "$(BUILDDIR)/$(OUTPUTEXE):")
for _, object := range objectFiles {
fmt.Fprintf(&output, " $(BUILDDIR)/%v", object.obj)
}
fmt.Fprint(&output, "\n")
fmt.Fprint(&output, "\t$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^\n\n")
// OBJECTS
for _, object := range objectFiles {
fmt.Fprintf(&output, "$(BUILDDIR)/%v: $(SRCDIR)/%v $(HEADERS)\n", object.obj, object.src)
fmt.Fprint(&output, "\t@mkdir -p $(@D)\n")
fmt.Fprint(&output, "\t$(CC) -c $(CFLAGS) -o $@ $<\n\n")
}
// PHONY
fmt.Fprint(&output, ".PHONY: clean\n\n")
fmt.Fprint(&output, "clean:\n\t@rm -r $(BUILDDIR)\n\n")
if err := os.WriteFile("Makefile", output.Bytes(), 0644); err != nil {
fmt.Printf("failed to write Makefile: %v\n", err)
os.Exit(1)
}
return
}
|