@@ -157,16 +157,29 @@ var aeabiBuiltins = []string{
157
157
158
158
func builtinFiles (target string ) []string {
159
159
builtins := append ([]string {}, genericBuiltins ... ) // copy genericBuiltins
160
- if target [: 3 ] == "arm" {
160
+ if strings . HasPrefix ( target , "arm" ) {
161
161
builtins = append (builtins , aeabiBuiltins ... )
162
162
}
163
163
return builtins
164
164
}
165
165
166
+ // builtinsDir returns the directory where the sources for compiler-rt are kept.
167
+ func builtinsDir () string {
168
+ return filepath .Join (sourceDir (), "lib" , "compiler-rt" , "lib" , "builtins" )
169
+ }
170
+
166
171
// Get the builtins archive, possibly generating it as needed.
167
172
func loadBuiltins (target string ) (path string , err error ) {
173
+ // Try to load a precompiled compiler-rt library.
174
+ precompiledPath := filepath .Join (sourceDir (), "pkg" , target , "compiler-rt.a" )
175
+ if _ , err := os .Stat (precompiledPath ); err == nil {
176
+ // Found a precompiled compiler-rt for this OS/architecture. Return the
177
+ // path directly.
178
+ return precompiledPath , nil
179
+ }
180
+
168
181
outfile := "librt-" + target + ".a"
169
- builtinsDir := filepath . Join ( sourceDir (), "lib" , "compiler-rt" , "lib" , "builtins" )
182
+ builtinsDir := builtinsDir ( )
170
183
171
184
builtins := builtinFiles (target )
172
185
srcs := make ([]string , len (builtins ))
@@ -178,9 +191,33 @@ func loadBuiltins(target string) (path string, err error) {
178
191
return path , err
179
192
}
180
193
181
- dir , err := ioutil .TempDir ("" , "tinygo-builtins" )
194
+ var cachepath string
195
+ err = compileBuiltins (target , func (path string ) error {
196
+ path , err := cacheStore (path , outfile , commands ["clang" ], srcs )
197
+ cachepath = path
198
+ return err
199
+ })
200
+ return cachepath , err
201
+ }
202
+
203
+ // compileBuiltins compiles builtins from compiler-rt into a static library.
204
+ // When it succeeds, it will call the callback with the resulting path. The path
205
+ // will be removed after callback returns. If callback returns an error, this is
206
+ // passed through to the return value of this function.
207
+ func compileBuiltins (target string , callback func (path string ) error ) error {
208
+ builtinsDir := builtinsDir ()
209
+
210
+ builtins := builtinFiles (target )
211
+ srcs := make ([]string , len (builtins ))
212
+ for i , name := range builtins {
213
+ srcs [i ] = filepath .Join (builtinsDir , name )
214
+ }
215
+
216
+ dirPrefix := "tinygo-builtins"
217
+ remapDir := filepath .Join (os .TempDir (), dirPrefix )
218
+ dir , err := ioutil .TempDir (os .TempDir (), dirPrefix )
182
219
if err != nil {
183
- return "" , err
220
+ return err
184
221
}
185
222
defer os .RemoveAll (dir )
186
223
@@ -195,13 +232,16 @@ func loadBuiltins(target string) (path string, err error) {
195
232
objpath := filepath .Join (dir , objname + ".o" )
196
233
objs = append (objs , objpath )
197
234
srcpath := filepath .Join (builtinsDir , name )
198
- cmd := exec .Command (commands ["clang" ], "-c" , "-Oz" , "-g" , "-Werror" , "-Wall" , "-std=c11" , "-fshort-enums" , "-nostdlibinc" , "-ffunction-sections" , "-fdata-sections" , "--target=" + target , "-o" , objpath , srcpath )
235
+ // Note: -fdebug-prefix-map is necessary to make the output archive
236
+ // reproducible. Otherwise the temporary directory is stored in the
237
+ // archive itself, which varies each run.
238
+ cmd := exec .Command (commands ["clang" ], "-c" , "-Oz" , "-g" , "-Werror" , "-Wall" , "-std=c11" , "-fshort-enums" , "-nostdlibinc" , "-ffunction-sections" , "-fdata-sections" , "--target=" + target , "-fdebug-prefix-map=" + dir + "=" + remapDir , "-o" , objpath , srcpath )
199
239
cmd .Stdout = os .Stdout
200
240
cmd .Stderr = os .Stderr
201
241
cmd .Dir = dir
202
242
err = cmd .Run ()
203
243
if err != nil {
204
- return "" , & commandError {"failed to build" , srcpath , err }
244
+ return & commandError {"failed to build" , srcpath , err }
205
245
}
206
246
}
207
247
@@ -213,8 +253,10 @@ func loadBuiltins(target string) (path string, err error) {
213
253
cmd .Dir = dir
214
254
err = cmd .Run ()
215
255
if err != nil {
216
- return "" , & commandError {"failed to make static library" , arpath , err }
256
+ return & commandError {"failed to make static library" , arpath , err }
217
257
}
218
258
219
- return cacheStore (arpath , outfile , commands ["clang" ], srcs )
259
+ // Give the caller the resulting file. The callback must copy the file,
260
+ // because after it returns the temporary directory will be removed.
261
+ return callback (arpath )
220
262
}
0 commit comments