@@ -40,8 +40,9 @@ func init() {
40
40
}
41
41
42
42
// Cross compilation docker containers
43
- var dockerBase = "techknowlogick/xgo:base"
44
- var dockerDist = "techknowlogick/xgo:"
43
+ var (
44
+ dockerDist = "techknowlogick/xgo:"
45
+ )
45
46
46
47
// Command line arguments to fine tune the compilation
47
48
var (
@@ -240,7 +241,6 @@ func checkDockerImage(image string) (bool, error) {
240
241
241
242
// compare output of docker images and image name
242
243
func compareOutAndImage (out []byte , image string ) (bool , error ) {
243
-
244
244
if strings .Contains (image , ":" ) {
245
245
// get repository and tag
246
246
res := strings .SplitN (image , ":" , 2 )
@@ -251,7 +251,6 @@ func compareOutAndImage(out []byte, image string) (bool, error) {
251
251
252
252
// default find repository without tag
253
253
return bytes .Contains (out , []byte (image )), nil
254
-
255
254
}
256
255
257
256
// Pulls an image from the docker registry.
@@ -265,8 +264,24 @@ func pullDockerImage(image string) error {
265
264
func compile (image string , config * ConfigFlags , flags * BuildFlags , folder string ) error {
266
265
// If a local build was requested, find the import path and mount all GOPATH sources
267
266
locals , mounts , paths := []string {}, []string {}, []string {}
268
- var usesModules bool
269
- if strings .HasPrefix (config .Repository , string (filepath .Separator )) || strings .HasPrefix (config .Repository , "." ) {
267
+
268
+ usesModules := true
269
+ localBuild := strings .HasPrefix (config .Repository , string (filepath .Separator )) || strings .HasPrefix (config .Repository , "." )
270
+
271
+ // We need to consider our module-aware status
272
+ go111module := os .Getenv ("GO111MODULE" )
273
+ if go111module == "off" {
274
+ usesModules = false
275
+ } else if go111module == "auto" {
276
+ // we need to look at the current config and determine if we should use modules...
277
+
278
+ if ! localBuild {
279
+ // This implies that we are using an url or module name for `go get`.
280
+ // We can't run `go get` here! So we cannot determine if this needs to be module-aware or not!
281
+ log .Fatalf ("Can only compile directories with GO111MODULE=auto" )
282
+ }
283
+
284
+ usesModules = false
270
285
if _ , err := os .Stat (config .Repository + "/go.mod" ); err == nil {
271
286
usesModules = true
272
287
}
@@ -278,58 +293,92 @@ func compile(image string, config *ConfigFlags, flags *BuildFlags, folder string
278
293
usesModules = true
279
294
}
280
295
}
296
+ if ! usesModules {
297
+ // Walk the parents looking for a go.mod file!
298
+ goModDir , err := filepath .Abs (config .Repository )
299
+ if err != nil {
300
+ log .Fatalf ("Failed to locate requested package: %v." , err )
301
+ }
302
+ // now walk backwards as per go behaviour
303
+ for {
304
+ if stat , err := os .Stat (filepath .Join (goModDir , "go.mod" )); err == nil {
305
+ usesModules = true
306
+ break
307
+ } else if stat .IsDir () {
308
+ break
309
+ }
310
+ parent := filepath .Dir (goModDir )
311
+ if len (parent ) >= len (goModDir ) {
312
+ break
313
+ }
314
+ goModDir = parent
315
+ }
316
+ }
317
+ }
281
318
319
+ if localBuild && ! usesModules {
320
+ // If we're performing a local build and we're not using modules we need to map the gopath over to the docker
321
+
322
+ // First determine the GOPATH
282
323
gopathEnv := os .Getenv ("GOPATH" )
283
- if gopathEnv == "" && ! usesModules {
324
+ if gopathEnv == "" {
284
325
log .Printf ("No $GOPATH is set - defaulting to %s" , build .Default .GOPATH )
285
326
gopathEnv = build .Default .GOPATH
286
327
}
287
328
288
- // Iterate over all the local libs and export the mount points
289
- if gopathEnv == "" && ! usesModules {
329
+ if gopathEnv == "" {
290
330
log .Fatalf ("No $GOPATH is set or forwarded to xgo" )
291
331
}
292
- if ! usesModules {
293
332
294
- for _ , gopath := range strings .Split (gopathEnv , string (os .PathListSeparator )) {
295
- // Since docker sandboxes volumes, resolve any symlinks manually
296
- sources := filepath .Join (gopath , "src" )
297
- filepath .Walk (sources , func (path string , info os.FileInfo , err error ) error {
298
- // Skip any folders that errored out
299
- if err != nil {
300
- log .Printf ("Failed to access GOPATH element %s: %v" , path , err )
301
- return nil
302
- }
303
- // Skip anything that's not a symlink
304
- if info .Mode ()& os .ModeSymlink == 0 {
305
- return nil
306
- }
307
- // Resolve the symlink and skip if it's not a folder
308
- target , err := filepath .EvalSymlinks (path )
309
- if err != nil {
310
- return nil
311
- }
312
- if info , err = os .Stat (target ); err != nil || ! info .IsDir () {
313
- return nil
314
- }
315
- // Skip if the symlink points within GOPATH
316
- if filepath .HasPrefix (target , sources ) {
333
+ // Iterate over all the local libs and export the mount points
334
+ for _ , gopath := range strings .Split (gopathEnv , string (os .PathListSeparator )) {
335
+ // Since docker sandboxes volumes, resolve any symlinks manually
336
+ sources := filepath .Join (gopath , "src" )
337
+ absSources , err := filepath .Abs (sources )
338
+ if err != nil {
339
+ log .Fatalf ("Unable to generate absolute path for source directory %s. %v" , sources , err )
340
+ }
341
+ absSources = filepath .ToSlash (filepath .Join (absSources , string (filepath .Separator )))
342
+ _ = filepath .Walk (sources , func (path string , info os.FileInfo , err error ) error {
343
+ // Skip any folders that errored out
344
+ if err != nil {
345
+ log .Printf ("Failed to access GOPATH element %s: %v" , path , err )
346
+ return nil
347
+ }
348
+ // Skip anything that's not a symlink
349
+ if info .Mode ()& os .ModeSymlink == 0 {
350
+ return nil
351
+ }
352
+ // Resolve the symlink and skip if it's not a folder
353
+ target , err := filepath .EvalSymlinks (path )
354
+ if err != nil {
355
+ return nil
356
+ }
357
+ if info , err = os .Stat (target ); err != nil || ! info .IsDir () {
358
+ return nil
359
+ }
360
+ // Skip if the symlink points within GOPATH
361
+ absTarget , err := filepath .Abs (target )
362
+ if err == nil {
363
+ absTarget = filepath .ToSlash (filepath .Join (absTarget , string (filepath .Separator )))
364
+ if strings .HasPrefix (absTarget , absSources ) {
317
365
return nil
318
366
}
367
+ }
319
368
320
- // Folder needs explicit mounting due to docker symlink security
321
- locals = append (locals , target )
322
- mounts = append (mounts , filepath .Join ("/ext-go" , strconv .Itoa (len (locals )), "src" , strings .TrimPrefix (path , sources )))
323
- paths = append (paths , filepath .Join ("/ext-go" , strconv .Itoa (len (locals ))))
324
- return nil
325
- })
326
- // Export the main mount point for this GOPATH entry
327
- locals = append (locals , sources )
328
- mounts = append (mounts , filepath .Join ("/ext-go" , strconv .Itoa (len (locals )), "src" ))
369
+ // Folder needs explicit mounting due to docker symlink security
370
+ locals = append (locals , target )
371
+ mounts = append (mounts , filepath .Join ("/ext-go" , strconv .Itoa (len (locals )), "src" , strings .TrimPrefix (path , sources )))
329
372
paths = append (paths , filepath .Join ("/ext-go" , strconv .Itoa (len (locals ))))
330
- }
373
+ return nil
374
+ })
375
+ // Export the main mount point for this GOPATH entry
376
+ locals = append (locals , sources )
377
+ mounts = append (mounts , filepath .Join ("/ext-go" , strconv .Itoa (len (locals )), "src" ))
378
+ paths = append (paths , filepath .Join ("/ext-go" , strconv .Itoa (len (locals ))))
331
379
}
332
380
}
381
+
333
382
// Assemble and run the cross compilation command
334
383
fmt .Printf ("Cross compiling %s...\n " , config .Repository )
335
384
@@ -383,27 +432,32 @@ func compile(image string, config *ConfigFlags, flags *BuildFlags, folder string
383
432
// Set ssh agent socket environment variable
384
433
args = append (args , "-e" , fmt .Sprintf ("SSH_AUTH_SOCK=%s" , os .Getenv ("SSH_AUTH_SOCK" )))
385
434
}
435
+
386
436
if usesModules {
387
437
args = append (args , []string {"-e" , "GO111MODULE=on" }... )
388
438
args = append (args , []string {"-v" , build .Default .GOPATH + ":/go" }... )
389
-
390
- // Map this repository to the /source folder
391
- absRepository , err := filepath .Abs (config .Repository )
392
- if err != nil {
393
- log .Fatalf ("Failed to locate requested module repository: %v." , err )
394
- }
395
- args = append (args , []string {"-v" , absRepository + ":/source" }... )
439
+ // FIXME: consider GOMODCACHE?
396
440
397
441
fmt .Printf ("Enabled Go module support\n " )
398
442
399
- // Check whether it has a vendor folder, and if so, use it
400
- vendorPath := absRepository + "/vendor"
401
- vendorfolder , err := os .Stat (vendorPath )
402
- if ! os .IsNotExist (err ) && vendorfolder .Mode ().IsDir () {
403
- args = append (args , []string {"-e" , "FLAG_MOD=vendor" }... )
404
- fmt .Printf ("Using vendored Go module dependencies\n " )
443
+ if localBuild {
444
+ // Map this repository to the /source folder
445
+ absRepository , err := filepath .Abs (config .Repository )
446
+ if err != nil {
447
+ log .Fatalf ("Failed to locate requested module repository: %v." , err )
448
+ }
449
+
450
+ args = append (args , []string {"-v" , absRepository + ":/source" }... )
451
+ // Check whether it has a vendor folder, and if so, use it
452
+ vendorPath := absRepository + "/vendor"
453
+ vendorfolder , err := os .Stat (vendorPath )
454
+ if ! os .IsNotExist (err ) && vendorfolder .Mode ().IsDir () {
455
+ args = append (args , []string {"-e" , "FLAG_MOD=vendor" }... )
456
+ fmt .Printf ("Using vendored Go module dependencies\n " )
457
+ }
405
458
}
406
459
} else {
460
+ args = append (args , []string {"-e" , "GO111MODULE=off" }... )
407
461
for i := 0 ; i < len (locals ); i ++ {
408
462
args = append (args , []string {"-v" , fmt .Sprintf ("%s:%s:ro" , locals [i ], mounts [i ])}... )
409
463
}
0 commit comments