github.com/jchengjr77/canaveral@v1.0.1-0.20200715160102-ea9245d1a2fb/csupport/addC.go (about) 1 package csupport 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "strings" 9 10 "github.com/jchengjr77/canaveral/lib" 11 ) 12 13 // createMainFile creates a basic projName.c file that uses stdlib.h 14 // to print "Canaveral is awesome!" in the main function 15 // * tested 16 func createMainFile(projName string) error { 17 err := lib.CreateFile(projName + ".c") 18 if err != nil { 19 return err 20 } 21 mainfile, err := os.OpenFile(projName+".c", os.O_APPEND|os.O_WRONLY, 0644) 22 defer func() { 23 err := mainfile.Close() 24 lib.Check(err) 25 }() 26 27 include := "#include <stdio.h>" 28 main := "int main() {\n\tprintf(\"Canaveral is awesome!" + `\n` + "\");\n\treturn 0;\n}\n" 29 30 _, err = mainfile.WriteString(include + "\n\n" + main) 31 return err 32 } 33 34 // createREADME creates a README.md file 35 // * tested 36 func createREADME(projName string) error { 37 err := lib.CreateFile("README.md") 38 if err != nil { 39 return err 40 } 41 readme, err := os.OpenFile("README.md", os.O_APPEND|os.O_WRONLY, 0644) 42 defer func() { 43 err := readme.Close() 44 lib.Check(err) 45 }() 46 header := "# " + projName 47 making := "## Compiling\nTo compile " + projName + "simply download it and run `make`. To clean old builds, run `make clean`" 48 canaveral := "###### Created with [Canaveral](https://github.com/jchengjr77/canaveral)" 49 _, err = readme.WriteString(header + "\n\n" + making + "\n\n" + canaveral) 50 return err 51 } 52 53 // createMakeFile creates a make file that compiles the projName.c file into 54 // a binary called projName 55 // * tested 56 func createMakeFile(projName string) error { 57 err := lib.CreateFile("Makefile") 58 if err != nil { 59 return err 60 } 61 62 make, err := os.OpenFile("Makefile", os.O_APPEND|os.O_WRONLY, 0644) 63 defer func() { 64 err := make.Close() 65 lib.Check(err) 66 }() 67 topComment := "# Basic makefile generated by Canaveral" 68 CC := "CC = gcc" 69 CFLAGS := "CFLAGS = -g -Og -Wall -std=c99 -I." 70 DEPS := "DEPS = " + projName + ".h" 71 oFiles := "%.o: %.c $(DEPS)\n\t$(CC) -c -o $@ $< $(CFLAGS)" 72 outfile := projName + ": " + projName + ".o\n\t$(CC) -o $@ $^ $(CFLAGS)" 73 PHONY := ".PHONY: clean" 74 clean := "clean:\n\trm -f *.o *~" 75 76 _, err = make.WriteString(topComment + "\n\n" + CC + "\n" + CFLAGS + "\n" + DEPS + "\n\n" + oFiles + "\n\n" + outfile + "\n\n" + PHONY + "\n" + clean) 77 return err 78 } 79 80 // AddToMake adds a dependency to a Makefile conforming to the style of the one 81 // created by canaveral. It takes in [filename].c, adds [filename].h to the 82 // DEPS definition and [filename].o to the make definition for the binary file 83 // [binaryAddTo] line of the form [binaryAddTo]: [file].o 84 // * tested 85 func AddToMake(filename, binaryAddTo string) error { 86 if !lib.FileExists(filename) { 87 return errors.New("File not found: " + filename) 88 } 89 if len(filename) < 2 || filename[len(filename)-2:] != ".c" { 90 return errors.New("Currently addmake only supports adding simple rules for compiling additional c files") 91 } 92 if !lib.FileExists("Makefile") { 93 return errors.New("Cannot find Makefile") 94 } 95 makefile, err := ioutil.ReadFile("Makefile") 96 if err != nil { 97 return err 98 } 99 100 addedDependency := false 101 addedOutfile := false 102 103 lines := strings.Split(string(makefile), "\n") 104 for i, line := range lines { 105 if len(line) >= 4 && line[0:4] == "DEPS" { 106 addedDependency = true 107 lines[i] = line + " " + filename[:len(filename)-2] + ".h" 108 } 109 if len(line) >= len(binaryAddTo) && line[:len(binaryAddTo)] == binaryAddTo { 110 addedOutfile = true 111 lines[i] = line + " " + filename[:len(filename)-2] + ".o" 112 } 113 } 114 115 if addedDependency && addedOutfile { 116 output := strings.Join(lines, "\n") 117 err = ioutil.WriteFile("Makefile", []byte(output), 0644) 118 return err 119 } 120 if !addedDependency { 121 return errors.New("Currently addmake only supports very simple Makefile additions, and the found Makefile doesn't conform to the necessary standards. Missing line: DEPS [file].h") 122 } 123 return errors.New("Currently addmake only supports very simple Makefile additions, and the found Makefile doesn't conform to the necessary standards. Missing line: " + binaryAddTo + ": [file].o") 124 } 125 126 // AddCProj launches a new C project. 127 // The main mechanism is similar to addProj (in root folder). 128 // It will create a Makefile, projName.c, and a projName.h file 129 // * tested 130 func AddCProj(projName string, wsPath string) { 131 // Get workspace path 132 ws, err := ioutil.ReadFile(wsPath) 133 lib.Check(err) 134 err = os.MkdirAll(string(ws)+"/"+projName, os.ModePerm) 135 lib.Check(err) 136 // Navigate to canaveral workspace 137 err = os.Chdir(string(ws) + "/" + projName) 138 lib.Check(err) 139 140 err = createMainFile(projName) 141 lib.Check(err) 142 err = lib.CreateFile(projName + ".h") 143 lib.Check(err) 144 err = createMakeFile(projName) 145 lib.Check(err) 146 err = createREADME(projName) 147 lib.Check(err) 148 149 fmt.Printf("Added C Project %s to workspace %s\n", projName, string(ws)) 150 }