github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/builder/mingw-w64.go (about) 1 package builder 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/tinygo-org/tinygo/goenv" 11 ) 12 13 var MinGW = Library{ 14 name: "mingw-w64", 15 makeHeaders: func(target, includeDir string) error { 16 // copy _mingw.h 17 srcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "mingw-w64") 18 outf, err := os.Create(includeDir + "/_mingw.h") 19 if err != nil { 20 return err 21 } 22 defer outf.Close() 23 inf, err := os.Open(srcDir + "/mingw-w64-headers/crt/_mingw.h.in") 24 if err != nil { 25 return err 26 } 27 _, err = io.Copy(outf, inf) 28 return err 29 }, 30 sourceDir: func() string { return "" }, // unused 31 cflags: func(target, headerPath string) []string { 32 // No flags necessary because there are no files to compile. 33 return nil 34 }, 35 librarySources: func(target string) ([]string, error) { 36 // We only use the UCRT DLL file. No source files necessary. 37 return nil, nil 38 }, 39 } 40 41 // makeMinGWExtraLibs returns a slice of jobs to import the correct .dll 42 // libraries. This is done by converting input .def files to .lib files which 43 // can then be linked as usual. 44 // 45 // TODO: cache the result. At the moment, it costs a few hundred milliseconds to 46 // compile these files. 47 func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob { 48 var jobs []*compileJob 49 root := goenv.Get("TINYGOROOT") 50 // Normally all the api-ms-win-crt-*.def files are all compiled to a single 51 // .lib file. But to simplify things, we're going to leave them as separate 52 // files. 53 for _, name := range []string{ 54 "kernel32.def.in", 55 "api-ms-win-crt-conio-l1-1-0.def", 56 "api-ms-win-crt-convert-l1-1-0.def.in", 57 "api-ms-win-crt-environment-l1-1-0.def", 58 "api-ms-win-crt-filesystem-l1-1-0.def", 59 "api-ms-win-crt-heap-l1-1-0.def", 60 "api-ms-win-crt-locale-l1-1-0.def", 61 "api-ms-win-crt-math-l1-1-0.def.in", 62 "api-ms-win-crt-multibyte-l1-1-0.def", 63 "api-ms-win-crt-private-l1-1-0.def.in", 64 "api-ms-win-crt-process-l1-1-0.def", 65 "api-ms-win-crt-runtime-l1-1-0.def.in", 66 "api-ms-win-crt-stdio-l1-1-0.def", 67 "api-ms-win-crt-string-l1-1-0.def", 68 "api-ms-win-crt-time-l1-1-0.def", 69 "api-ms-win-crt-utility-l1-1-0.def", 70 } { 71 outpath := filepath.Join(tmpdir, filepath.Base(name)+".lib") 72 inpath := filepath.Join(root, "lib/mingw-w64/mingw-w64-crt/lib-common/"+name) 73 job := &compileJob{ 74 description: "create lib file " + inpath, 75 result: outpath, 76 run: func(job *compileJob) error { 77 defpath := inpath 78 var archDef, emulation string 79 switch goarch { 80 case "amd64": 81 archDef = "-DDEF_X64" 82 emulation = "i386pep" 83 case "arm64": 84 archDef = "-DDEF_ARM64" 85 emulation = "arm64pe" 86 default: 87 return fmt.Errorf("unsupported architecture for mingw-w64: %s", goarch) 88 } 89 if strings.HasSuffix(inpath, ".in") { 90 // .in files need to be preprocessed by a preprocessor (-E) 91 // first. 92 defpath = outpath + ".def" 93 err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", archDef, "-DDATA", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/") 94 if err != nil { 95 return err 96 } 97 } 98 return link("ld.lld", "-m", emulation, "-o", outpath, defpath) 99 }, 100 } 101 jobs = append(jobs, job) 102 } 103 return jobs 104 }