runtime: Remove now unnecessary pad field from ParFor.

It is not needed due to the removal of the ctx field.
    
    Reviewed-on: https://go-review.googlesource.com/16525

From-SVN: r229616
This commit is contained in:
Ian Lance Taylor 2015-10-31 00:59:47 +00:00
parent 725e1be340
commit af146490bb
1007 changed files with 86529 additions and 30520 deletions

View File

@ -1,4 +1,4 @@
16f69a4007a1903da4055a496882b514e05f45f3 4b6b496579225cdd897130f6d6fd18ecb100bf99
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.

View File

@ -1,4 +1,4 @@
883bc6ed0ea815293fe6309d66f967ea60630e87 bb03defe933c89fee44be675d7aa0fbd893ced30
The first line of this file holds the git revision number of the The first line of this file holds the git revision number of the
last merge done from the master library sources. last merge done from the master library sources.

View File

@ -233,12 +233,15 @@ toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \ toolexeclibgogo_DATA = \
go/ast.gox \ go/ast.gox \
go/build.gox \ go/build.gox \
go/constant.gox \
go/doc.gox \ go/doc.gox \
go/format.gox \ go/format.gox \
go/importer.gox \
go/parser.gox \ go/parser.gox \
go/printer.gox \ go/printer.gox \
go/scanner.gox \ go/scanner.gox \
go/token.gox go/token.gox \
go/types.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash toolexeclibgohashdir = $(toolexeclibgodir)/hash
@ -292,7 +295,8 @@ toolexeclibgomath_DATA = \
toolexeclibgomimedir = $(toolexeclibgodir)/mime toolexeclibgomimedir = $(toolexeclibgodir)/mime
toolexeclibgomime_DATA = \ toolexeclibgomime_DATA = \
mime/multipart.gox mime/multipart.gox \
mime/quotedprintable.gox
toolexeclibgonetdir = $(toolexeclibgodir)/net toolexeclibgonetdir = $(toolexeclibgodir)/net
@ -676,46 +680,74 @@ go_math_files = \
go/math/tanh.go \ go/math/tanh.go \
go/math/unsafe.go go/math/unsafe.go
if LIBGO_IS_OPENBSD
go_mime_type_file = go/mime/type_openbsd.go
else
if LIBGO_IS_FREEBSD
go_mime_type_file = go/mime/type_freebsd.go
else
if LIBGO_IS_DRAGONFLY
go_mime_type_file = go/mime/type_dragonfly.go
else
go_mime_type_file =
endif
endif
endif
go_mime_files = \ go_mime_files = \
go/mime/encodedword.go \
go/mime/grammar.go \ go/mime/grammar.go \
go/mime/mediatype.go \ go/mime/mediatype.go \
go/mime/type.go \ go/mime/type.go \
go/mime/type_unix.go go/mime/type_unix.go \
$(go_mime_type_file)
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
go_net_cgo_file = go/net/cgo_linux.go go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go go_net_sockopt_file = go/net/sockopt_linux.go
go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else else
if LIBGO_IS_IRIX if LIBGO_IS_IRIX
go_net_cgo_file = go/net/cgo_linux.go go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go go_net_sockopt_file = go/net/sockopt_linux.go
go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else else
if LIBGO_IS_SOLARIS if LIBGO_IS_SOLARIS
go_net_cgo_file = go/net/cgo_linux.go go_net_cgo_file = go/net/cgo_solaris.go
go_net_sock_file = go/net/sock_stub.go go_net_sock_file = go/net/sock_stub.go
go_net_sockopt_file = go/net/sockopt_solaris.go go_net_sockopt_file = go/net/sockopt_solaris.go
go_net_sockoptip_file = go/net/sockoptip_stub.go go_net_sockoptip_file = go/net/sockoptip_stub.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else else
if LIBGO_IS_FREEBSD if LIBGO_IS_FREEBSD
go_net_cgo_file = go/net/cgo_bsd.go go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resold.go
else else
if LIBGO_IS_NETBSD if LIBGO_IS_NETBSD
go_net_cgo_file = go/net/cgo_netbsd.go go_net_cgo_file = go/net/cgo_netbsd.go
go_net_sock_file = go/net/sock_bsd.go go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else else
go_net_cgo_file = go/net/cgo_bsd.go go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resold.go
endif endif
endif endif
endif endif
@ -731,10 +763,14 @@ else
if LIBGO_IS_DRAGONFLY if LIBGO_IS_DRAGONFLY
go_net_sendfile_file = go/net/sendfile_dragonfly.go go_net_sendfile_file = go/net/sendfile_dragonfly.go
else else
if LIBGO_IS_SOLARIS
go_net_sendfile_file = go/net/sendfile_solaris.go
else
go_net_sendfile_file = go/net/sendfile_stub.go go_net_sendfile_file = go/net/sendfile_stub.go
endif endif
endif endif
endif endif
endif
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
go_net_interface_file = go/net/interface_linux.go go_net_interface_file = go/net/interface_linux.go
@ -775,15 +811,22 @@ endif
endif endif
go_net_common_files = \ go_net_common_files = \
go/net/addrselect.go \
$(go_net_cloexec_file) \ $(go_net_cloexec_file) \
go/net/conf.go \
go/net/dial.go \ go/net/dial.go \
go/net/dnsclient.go \ go/net/dnsclient.go \
go/net/dnsclient_unix.go \ go/net/dnsclient_unix.go \
go/net/dnsconfig_unix.go \ go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \ go/net/dnsmsg.go \
go/net/fd_mutex.go \ go/net/fd_mutex.go \
go/net/fd_posix.go \
go/net/fd_unix.go \ go/net/fd_unix.go \
go/net/file.go \
go/net/file_unix.go \ go/net/file_unix.go \
go/net/hook.go \
go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \ go/net/hosts.go \
go/net/interface.go \ go/net/interface.go \
$(go_net_interface_file) \ $(go_net_interface_file) \
@ -796,6 +839,7 @@ go_net_common_files = \
go/net/lookup_unix.go \ go/net/lookup_unix.go \
go/net/mac.go \ go/net/mac.go \
go/net/net.go \ go/net/net.go \
go/net/nss.go \
go/net/parse.go \ go/net/parse.go \
go/net/pipe.go \ go/net/pipe.go \
go/net/fd_poll_runtime.go \ go/net/fd_poll_runtime.go \
@ -803,7 +847,6 @@ go_net_common_files = \
go/net/port_unix.go \ go/net/port_unix.go \
go/net/race0.go \ go/net/race0.go \
$(go_net_sendfile_file) \ $(go_net_sendfile_file) \
go/net/singleflight.go \
go/net/sock_posix.go \ go/net/sock_posix.go \
$(go_net_sock_file) \ $(go_net_sock_file) \
go/net/sockopt_posix.go \ go/net/sockopt_posix.go \
@ -821,6 +864,8 @@ go_net_common_files = \
go_net_files = \ go_net_files = \
go/net/cgo_unix.go \ go/net/cgo_unix.go \
$(go_net_cgo_file) \ $(go_net_cgo_file) \
$(go_net_cgo_res_file) \
$(go_net_cgo_sock_file) \
$(go_net_common_files) $(go_net_common_files)
go_netgo_files = \ go_netgo_files = \
@ -919,6 +964,32 @@ else
go_os_pipe_file = go/os/pipe_bsd.go go_os_pipe_file = go/os/pipe_bsd.go
endif endif
if LIBGO_IS_DARWIN
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_DRAGONFLY
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_FREEBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_NETBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_OPENBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_SOLARIS
go_os_sticky_file = go/os/sticky_bsd.go
else
go_os_sticky_file = go/os/sticky_notbsd.go
endif
endif
endif
endif
endif
endif
go_os_files = \ go_os_files = \
$(go_os_dir_file) \ $(go_os_dir_file) \
go/os/dir.go \ go/os/dir.go \
@ -939,6 +1010,7 @@ go_os_files = \
$(go_os_pipe_file) \ $(go_os_pipe_file) \
go/os/proc.go \ go/os/proc.go \
$(go_os_stat_file) \ $(go_os_stat_file) \
$(go_os_sticky_file) \
go/os/str.go \ go/os/str.go \
$(go_os_sys_file) \ $(go_os_sys_file) \
$(go_os_cloexec_file) \ $(go_os_cloexec_file) \
@ -959,6 +1031,7 @@ go_reflect_makefunc_c_file = \
go/reflect/makefunc_ffi_c.c go/reflect/makefunc_ffi_c.c
go_regexp_files = \ go_regexp_files = \
go/regexp/backtrack.go \
go/regexp/exec.go \ go/regexp/exec.go \
go/regexp/onepass.go \ go/regexp/onepass.go \
go/regexp/regexp.go go/regexp/regexp.go
@ -974,7 +1047,6 @@ go_runtime_files = \
go/runtime/error.go \ go/runtime/error.go \
go/runtime/extern.go \ go/runtime/extern.go \
go/runtime/mem.go \ go/runtime/mem.go \
go/runtime/softfloat64.go \
version.go version.go
version.go: s-version; @true version.go: s-version; @true
@ -1012,6 +1084,7 @@ go_strconv_files = \
go/strconv/atof.go \ go/strconv/atof.go \
go/strconv/atoi.go \ go/strconv/atoi.go \
go/strconv/decimal.go \ go/strconv/decimal.go \
go/strconv/doc.go \
go/strconv/extfloat.go \ go/strconv/extfloat.go \
go/strconv/ftoa.go \ go/strconv/ftoa.go \
go/strconv/isprint.go \ go/strconv/isprint.go \
@ -1019,6 +1092,7 @@ go_strconv_files = \
go/strconv/quote.go go/strconv/quote.go
go_strings_files = \ go_strings_files = \
go/strings/compare.go \
go/strings/reader.go \ go/strings/reader.go \
go/strings/replace.go \ go/strings/replace.go \
go/strings/search.go \ go/strings/search.go \
@ -1048,6 +1122,7 @@ endif
endif endif
go_log_syslog_files = \ go_log_syslog_files = \
go/log/syslog/doc.go \
go/log/syslog/syslog.go \ go/log/syslog/syslog.go \
$(go_syslog_file) $(go_syslog_file)
go_syslog_c_files = \ go_syslog_c_files = \
@ -1186,6 +1261,7 @@ crypto_rand_file =
endif endif
go_crypto_rand_files = \ go_crypto_rand_files = \
go/crypto/rand/eagain.go \
go/crypto/rand/rand.go \ go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \ go/crypto/rand/rand_unix.go \
$(crypto_rand_file) \ $(crypto_rand_file) \
@ -1222,6 +1298,37 @@ go_crypto_tls_files = \
go/crypto/tls/prf.go \ go/crypto/tls/prf.go \
go/crypto/tls/ticket.go \ go/crypto/tls/ticket.go \
go/crypto/tls/tls.go go/crypto/tls/tls.go
if LIBGO_IS_LINUX
go_crypto_x509_root_file = go/crypto/x509/root_linux.go
else
if LIBGO_IS_SOLARIS
go_crypto_x509_root_file = go/crypto/x509/root_solaris.go
else
if LIBGO_IS_DRAGONFLY
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_FREEBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_NETBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_OPENBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_DARWIN
go_crypto_x509_root_file = go/crypto/x509/root_darwin.go
else
go_crypto_x509_root_file =
endif
endif
endif
endif
endif
endif
endif
go_crypto_x509_files = \ go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \ go/crypto/x509/cert_pool.go \
go/crypto/x509/pem_decrypt.go \ go/crypto/x509/pem_decrypt.go \
@ -1229,6 +1336,7 @@ go_crypto_x509_files = \
go/crypto/x509/pkcs8.go \ go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \ go/crypto/x509/root.go \
go/crypto/x509/root_unix.go \ go/crypto/x509/root_unix.go \
$(go_crypto_x509_root_file) \
go/crypto/x509/sec1.go \ go/crypto/x509/sec1.go \
go/crypto/x509/verify.go \ go/crypto/x509/verify.go \
go/crypto/x509/x509.go go/crypto/x509/x509.go
@ -1246,6 +1354,7 @@ go_database_sql_driver_files = \
go_debug_dwarf_files = \ go_debug_dwarf_files = \
go/debug/dwarf/buf.go \ go/debug/dwarf/buf.go \
go/debug/dwarf/class_string.go \
go/debug/dwarf/const.go \ go/debug/dwarf/const.go \
go/debug/dwarf/entry.go \ go/debug/dwarf/entry.go \
go/debug/dwarf/line.go \ go/debug/dwarf/line.go \
@ -1337,6 +1446,9 @@ go_go_build_files = \
go/go/build/doc.go \ go/go/build/doc.go \
go/go/build/read.go \ go/go/build/read.go \
go/go/build/syslist.go go/go/build/syslist.go
go_go_constant_files = \
go/go/constant/go14.go \
go/go/constant/value.go
go_go_doc_files = \ go_go_doc_files = \
go/go/doc/comment.go \ go/go/doc/comment.go \
go/go/doc/doc.go \ go/go/doc/doc.go \
@ -1347,6 +1459,8 @@ go_go_doc_files = \
go/go/doc/synopsis.go go/go/doc/synopsis.go
go_go_format_files = \ go_go_format_files = \
go/go/format/format.go go/go/format/format.go
go_go_importer_files = \
go/go/importer/importer.go
go_go_parser_files = \ go_go_parser_files = \
go/go/parser/interface.go \ go/go/parser/interface.go \
go/go/parser/parser.go go/go/parser/parser.go
@ -1360,6 +1474,47 @@ go_go_token_files = \
go/go/token/position.go \ go/go/token/position.go \
go/go/token/serialize.go \ go/go/token/serialize.go \
go/go/token/token.go go/go/token/token.go
go_go_types_files = \
go/go/types/api.go \
go/go/types/assignments.go \
go/go/types/builtins.go \
go/go/types/call.go \
go/go/types/check.go \
go/go/types/conversions.go \
go/go/types/decl.go \
go/go/types/errors.go \
go/go/types/eval.go \
go/go/types/expr.go \
go/go/types/exprstring.go \
go/go/types/go12.go \
go/go/types/initorder.go \
go/go/types/labels.go \
go/go/types/lookup.go \
go/go/types/methodset.go \
go/go/types/object.go \
go/go/types/objset.go \
go/go/types/operand.go \
go/go/types/ordering.go \
go/go/types/package.go \
go/go/types/predicates.go \
go/go/types/resolver.go \
go/go/types/return.go \
go/go/types/scope.go \
go/go/types/selection.go \
go/go/types/stmt.go \
go/go/types/sizes.go \
go/go/types/type.go \
go/go/types/typestring.go \
go/go/types/typexpr.go \
go/go/types/universe.go
go_go_internal_gcimporter_files = \
go/go/internal/gcimporter/exportdata.go \
go/go/internal/gcimporter/gcimporter.go
go_go_internal_gccgoimporter_files = \
go/go/internal/gccgoimporter/gccgoinstallation.go \
go/go/internal/gccgoimporter/importer.go \
go/go/internal/gccgoimporter/parser.go
go_hash_adler32_files = \ go_hash_adler32_files = \
go/hash/adler32/adler32.go go/hash/adler32/adler32.go
@ -1399,6 +1554,10 @@ go_image_gif_files = \
go/image/gif/reader.go \ go/image/gif/reader.go \
go/image/gif/writer.go go/image/gif/writer.go
go_image_internal_imageutil_files = \
go/image/internal/imageutil/imageutil.go \
go/image/internal/imageutil/impl.go
go_image_jpeg_files = \ go_image_jpeg_files = \
go/image/jpeg/fdct.go \ go/image/jpeg/fdct.go \
go/image/jpeg/huffman.go \ go/image/jpeg/huffman.go \
@ -1416,15 +1575,46 @@ go_index_suffixarray_files = \
go/index/suffixarray/qsufsort.go \ go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go go/index/suffixarray/suffixarray.go
go_internal_format_files = \
go/internal/format/format.go
go_internal_singleflight_files = \
go/internal/singleflight/singleflight.go
if LIBGO_IS_LINUX
internal_syscall_unix_getrandom_file = go/internal/syscall/unix/getrandom_linux.go
else
internal_syscall_unix_getrandom_file =
endif
go_internal_syscall_unix_files = \
go/internal/syscall/unix/dummy.go \
$(internal_syscall_unix_getrandom_file)
go_internal_testenv_files = \
go/internal/testenv/testenv.go
go_internal_trace_files = \
go/internal/trace/goroutines.go \
go/internal/trace/parser.go
go_io_ioutil_files = \ go_io_ioutil_files = \
go/io/ioutil/ioutil.go \ go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go go/io/ioutil/tempfile.go
go_math_big_files = \ go_math_big_files = \
go/math/big/accuracy_string.go \
go/math/big/arith.go \ go/math/big/arith.go \
go/math/big/arith_decl_pure.go \
go/math/big/decimal.go \
go/math/big/float.go \
go/math/big/floatconv.go \
go/math/big/ftoa.go \
go/math/big/int.go \ go/math/big/int.go \
go/math/big/intconv.go \
go/math/big/nat.go \ go/math/big/nat.go \
go/math/big/rat.go go/math/big/natconv.go \
go/math/big/rat.go \
go/math/big/ratconv.go \
go/math/big/roundingmode_string.go
go_math_cmplx_files = \ go_math_cmplx_files = \
go/math/cmplx/abs.go \ go/math/cmplx/abs.go \
go/math/cmplx/asin.go \ go/math/cmplx/asin.go \
@ -1450,9 +1640,12 @@ go_math_rand_files = \
go_mime_multipart_files = \ go_mime_multipart_files = \
go/mime/multipart/formdata.go \ go/mime/multipart/formdata.go \
go/mime/multipart/multipart.go \ go/mime/multipart/multipart.go \
go/mime/multipart/quotedprintable.go \
go/mime/multipart/writer.go go/mime/multipart/writer.go
go_mime_quotedprintable_files = \
go/mime/quotedprintable/reader.go \
go/mime/quotedprintable/writer.go
go_net_http_files = \ go_net_http_files = \
go/net/http/client.go \ go/net/http/client.go \
go/net/http/cookie.go \ go/net/http/cookie.go \
@ -1504,6 +1697,23 @@ go_net_http_httputil_files = \
go_net_http_internal_files = \ go_net_http_internal_files = \
go/net/http/internal/chunked.go go/net/http/internal/chunked.go
if LIBGO_IS_LINUX
go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
else
if LIBGO_IS_FREEBSD
go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
else
go_net_internal_socktest_sys =
endif
endif
go_net_internal_socktest_files = \
go/net/internal/socktest/switch.go \
go/net/internal/socktest/switch_posix.go \
go/net/internal/socktest/switch_unix.go \
go/net/internal/socktest/sys_unix.go \
$(go_net_internal_socktest_sys)
go_old_regexp_files = \ go_old_regexp_files = \
go/old/regexp/regexp.go go/old/regexp/regexp.go
go_old_template_files = \ go_old_template_files = \
@ -1514,6 +1724,7 @@ go_old_template_files = \
go_os_exec_files = \ go_os_exec_files = \
go/os/exec/exec.go \ go/os/exec/exec.go \
go/os/exec/exec_posix.go \
go/os/exec/lp_unix.go go/os/exec/lp_unix.go
go_os_signal_files = \ go_os_signal_files = \
@ -1565,6 +1776,7 @@ go_text_template_files = \
go/text/template/exec.go \ go/text/template/exec.go \
go/text/template/funcs.go \ go/text/template/funcs.go \
go/text/template/helper.go \ go/text/template/helper.go \
go/text/template/option.go \
go/text/template/template.go go/text/template/template.go
go_text_template_parse_files = \ go_text_template_parse_files = \
go/text/template/parse/lex.go \ go/text/template/parse/lex.go \
@ -1767,6 +1979,12 @@ else
syscall_creds_test_file = syscall_creds_test_file =
endif endif
if LIBGO_IS_LINUX
syscall_exec_test_file = go/syscall/exec_linux_test.go go/syscall/syscall_linux_test.go
else
syscall_exec_test_file =
endif
go_base_syscall_files = \ go_base_syscall_files = \
go/syscall/env_unix.go \ go/syscall/env_unix.go \
go/syscall/syscall_errno.go \ go/syscall/syscall_errno.go \
@ -1810,21 +2028,14 @@ go_syscall_c_files = \
go_syscall_test_files = \ go_syscall_test_files = \
$(syscall_creds_test_file) \ $(syscall_creds_test_file) \
$(syscall_exec_test_file) \
go/syscall/exec_unix_test.go \
go/syscall/export_test.go \ go/syscall/export_test.go \
go/syscall/export_unix_test.go \
go/syscall/mmap_unix_test.go \ go/syscall/mmap_unix_test.go \
go/syscall/syscall_test.go \ go/syscall/syscall_test.go \
go/syscall/syscall_unix_test.go go/syscall/syscall_unix_test.go
if LIBGO_IS_LINUX
internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go
else
internal_syscall_getrandom_file =
endif
go_internal_syscall_files = \
go/internal/syscall/dummy.go \
$(internal_syscall_getrandom_file)
libcalls.go: s-libcalls; @true libcalls.go: s-libcalls; @true
s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files) s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
rm -f libcalls.go.tmp rm -f libcalls.go.tmp
@ -1978,12 +2189,17 @@ libgo_go_objs = \
html/template.lo \ html/template.lo \
go/ast.lo \ go/ast.lo \
go/build.lo \ go/build.lo \
go/constant.lo \
go/doc.lo \ go/doc.lo \
go/format.lo \ go/format.lo \
go/importer.lo \
go/internal/gcimporter.lo \
go/internal/gccgoimporter.lo \
go/parser.lo \ go/parser.lo \
go/printer.lo \ go/printer.lo \
go/scanner.lo \ go/scanner.lo \
go/token.lo \ go/token.lo \
go/types.lo \
hash/adler32.lo \ hash/adler32.lo \
hash/crc32.lo \ hash/crc32.lo \
hash/crc64.lo \ hash/crc64.lo \
@ -1999,10 +2215,15 @@ libgo_go_objs = \
image/color/palette.lo \ image/color/palette.lo \
image/draw.lo \ image/draw.lo \
image/gif.lo \ image/gif.lo \
image/internal/imageutil.lo \
image/jpeg.lo \ image/jpeg.lo \
image/png.lo \ image/png.lo \
index/suffixarray.lo \ index/suffixarray.lo \
internal/syscall.lo \ internal/format.lo \
internal/singleflight.lo \
internal/syscall/unix.lo \
internal/testenv.lo \
internal/trace.lo \
io/ioutil.lo \ io/ioutil.lo \
log/syslog.lo \ log/syslog.lo \
log/syslog/syslog_c.lo \ log/syslog/syslog_c.lo \
@ -2010,7 +2231,9 @@ libgo_go_objs = \
math/cmplx.lo \ math/cmplx.lo \
math/rand.lo \ math/rand.lo \
mime/multipart.lo \ mime/multipart.lo \
mime/quotedprintable.lo \
net/http.lo \ net/http.lo \
net/internal/socktest.lo \
net/mail.lo \ net/mail.lo \
net/rpc.lo \ net/rpc.lo \
net/smtp.lo \ net/smtp.lo \
@ -2121,11 +2344,11 @@ CHECK = \
$(MKDIR_P) $(@D); \ $(MKDIR_P) $(@D); \
rm -f $@-testsum $@-testlog; \ rm -f $@-testsum $@-testlog; \
if test "$(USE_DEJAGNU)" = "yes"; then \ if test "$(USE_DEJAGNU)" = "yes"; then \
$(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
elif test "$(GOBENCH)" != ""; then \ elif test "$(GOBENCH)" != ""; then \
$(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
else \ else \
if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \ if $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
echo "PASS: $(@D)" >> $@-testlog; \ echo "PASS: $(@D)" >> $@-testlog; \
echo "PASS: $(@D)"; \ echo "PASS: $(@D)"; \
echo "PASS: $(@D)" > $@-testsum; \ echo "PASS: $(@D)" > $@-testsum; \
@ -2910,6 +3133,15 @@ go/build/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/build/check .PHONY: go/build/check
@go_include@ go/constant.lo.dep
go/constant.lo.dep: $(go_go_constant_files)
$(BUILDDEPS)
go/constant.lo: $(go_go_constant_files)
$(BUILDPACKAGE)
go/constant/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/constant/check
@go_include@ go/doc.lo.dep @go_include@ go/doc.lo.dep
go/doc.lo.dep: $(go_go_doc_files) go/doc.lo.dep: $(go_go_doc_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -2928,6 +3160,15 @@ go/format/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/format/check .PHONY: go/format/check
@go_include@ go/importer.lo.dep
go/importer.lo.dep: $(go_go_importer_files)
$(BUILDDEPS)
go/importer.lo: $(go_go_importer_files)
$(BUILDPACKAGE)
go/importer/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/importer/check
@go_include@ go/parser.lo.dep @go_include@ go/parser.lo.dep
go/parser.lo.dep: $(go_go_parser_files) go/parser.lo.dep: $(go_go_parser_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -2964,6 +3205,33 @@ go/token/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/token/check .PHONY: go/token/check
@go_include@ go/types.lo.dep
go/types.lo.dep: $(go_go_types_files)
$(BUILDDEPS)
go/types.lo: $(go_go_types_files)
$(BUILDPACKAGE)
go/types/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/types/check
@go_include@ go/internal/gcimporter.lo.dep
go/internal/gcimporter.lo.dep: $(go_go_internal_gcimporter_files)
$(BUILDDEPS)
go/internal/gcimporter.lo: $(go_go_internal_gcimporter_files)
$(BUILDPACKAGE)
go/internal/gcimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gcimporter/check
@go_include@ go/internal/gccgoimporter.lo.dep
go/internal/gccgoimporter.lo.dep: $(go_go_internal_gccgoimporter_files)
$(BUILDDEPS)
go/internal/gccgoimporter.lo: $(go_go_internal_gccgoimporter_files)
$(BUILDPACKAGE)
go/internal/gccgoimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gccgoimporter/check
@go_include@ hash/adler32.lo.dep @go_include@ hash/adler32.lo.dep
hash/adler32.lo.dep: $(go_hash_adler32_files) hash/adler32.lo.dep: $(go_hash_adler32_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -3036,6 +3304,15 @@ image/gif/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: image/gif/check .PHONY: image/gif/check
@go_include@ image/internal/imageutil.lo.dep
image/internal/imageutil.lo.dep: $(go_image_internal_imageutil_files)
$(BUILDDEPS)
image/internal/imageutil.lo: $(go_image_internal_imageutil_files)
$(BUILDPACKAGE)
image/internal/imageutil/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/internal/imageutil/check
@go_include@ image/jpeg.lo.dep @go_include@ image/jpeg.lo.dep
image/jpeg.lo.dep: $(go_image_jpeg_files) image/jpeg.lo.dep: $(go_image_jpeg_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -3063,6 +3340,51 @@ index/suffixarray/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: index/suffixarray/check .PHONY: index/suffixarray/check
@go_include@ internal/format.lo.dep
internal/format.lo.dep: $(go_internal_format_files)
$(BUILDDEPS)
internal/format.lo: $(go_internal_format_files)
$(BUILDPACKAGE)
internal/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/format/check
@go_include@ internal/singleflight.lo.dep
internal/singleflight.lo.dep: $(go_internal_singleflight_files)
$(BUILDDEPS)
internal/singleflight.lo: $(go_internal_singleflight_files)
$(BUILDPACKAGE)
internal/singleflight/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/singleflight/check
@go_include@ internal/syscall/unix.lo.dep
internal/syscall/unix.lo.dep: $(go_internal_syscall_unix_files)
$(BUILDDEPS)
internal/syscall/unix.lo: $(go_internal_syscall_unix_files)
$(BUILDPACKAGE)
internal/syscall/unix/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/unix/check
@go_include@ internal/testenv.lo.dep
internal/testenv.lo.dep: $(go_internal_testenv_files)
$(BUILDDEPS)
internal/testenv.lo: $(go_internal_testenv_files)
$(BUILDPACKAGE)
internal/testenv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/testenv/check
@go_include@ internal/trace.lo.dep
internal/trace.lo.dep: $(go_internal_trace_files)
$(BUILDDEPS)
internal/trace.lo: $(go_internal_trace_files)
$(BUILDPACKAGE)
internal/trace/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/trace/check
@go_include@ io/ioutil.lo.dep @go_include@ io/ioutil.lo.dep
io/ioutil.lo.dep: $(go_io_ioutil_files) io/ioutil.lo.dep: $(go_io_ioutil_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -3120,6 +3442,15 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: mime/multipart/check .PHONY: mime/multipart/check
@go_include@ mime/quotedprintable.lo.dep
mime/quotedprintable.lo.dep: $(go_mime_quotedprintable_files)
$(BUILDDEPS)
mime/quotedprintable.lo: $(go_mime_quotedprintable_files)
$(BUILDPACKAGE)
mime/quotedprintable/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/quotedprintable/check
@go_include@ net/http.lo.dep @go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files) net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -3237,6 +3568,15 @@ net/http/pprof/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: net/http/pprof/check .PHONY: net/http/pprof/check
@go_include@ net/internal/socktest.lo.dep
net/internal/socktest.lo.dep: $(go_net_internal_socktest_files)
$(BUILDDEPS)
net/internal/socktest.lo: $(go_net_internal_socktest_files)
$(BUILDPACKAGE)
net/internal/socktest/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/internal/socktest/check
@go_include@ net/rpc/jsonrpc.lo.dep @go_include@ net/rpc/jsonrpc.lo.dep
net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files) net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -3432,15 +3772,6 @@ syscall/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: syscall/check .PHONY: syscall/check
@go_include@ internal/syscall.lo.dep
internal/syscall.lo.dep: $(go_internal_syscall_files)
$(BUILDDEPS)
internal/syscall.lo: $(go_internal_syscall_files)
$(BUILDPACKAGE)
internal/syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/check
# How to build a .gox file from a .lo file. # How to build a .gox file from a .lo file.
BUILDGOX = \ BUILDGOX = \
f=`echo $< | sed -e 's/.lo$$/.o/'`; \ f=`echo $< | sed -e 's/.lo$$/.o/'`; \
@ -3620,10 +3951,14 @@ go/ast.gox: go/ast.lo
$(BUILDGOX) $(BUILDGOX)
go/build.gox: go/build.lo go/build.gox: go/build.lo
$(BUILDGOX) $(BUILDGOX)
go/constant.gox: go/constant.lo
$(BUILDGOX)
go/doc.gox: go/doc.lo go/doc.gox: go/doc.lo
$(BUILDGOX) $(BUILDGOX)
go/format.gox: go/format.lo go/format.gox: go/format.lo
$(BUILDGOX) $(BUILDGOX)
go/importer.gox: go/importer.lo
$(BUILDGOX)
go/parser.gox: go/parser.lo go/parser.gox: go/parser.lo
$(BUILDGOX) $(BUILDGOX)
go/printer.gox: go/printer.lo go/printer.gox: go/printer.lo
@ -3632,6 +3967,13 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX) $(BUILDGOX)
go/token.gox: go/token.lo go/token.gox: go/token.lo
$(BUILDGOX) $(BUILDGOX)
go/types.gox: go/types.lo
$(BUILDGOX)
go/internal/gcimporter.gox: go/internal/gcimporter.lo
$(BUILDGOX)
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
$(BUILDGOX)
hash/adler32.gox: hash/adler32.lo hash/adler32.gox: hash/adler32.lo
$(BUILDGOX) $(BUILDGOX)
@ -3648,6 +3990,8 @@ image/draw.gox: image/draw.lo
$(BUILDGOX) $(BUILDGOX)
image/gif.gox: image/gif.lo image/gif.gox: image/gif.lo
$(BUILDGOX) $(BUILDGOX)
image/internal/imageutil.gox: image/internal/imageutil.lo
$(BUILDGOX)
image/jpeg.gox: image/jpeg.lo image/jpeg.gox: image/jpeg.lo
$(BUILDGOX) $(BUILDGOX)
image/png.gox: image/png.lo image/png.gox: image/png.lo
@ -3659,6 +4003,17 @@ image/color/palette.gox: image/color/palette.lo
index/suffixarray.gox: index/suffixarray.lo index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX) $(BUILDGOX)
internal/format.gox: internal/format.lo
$(BUILDGOX)
internal/singleflight.gox: internal/singleflight.lo
$(BUILDGOX)
internal/syscall/unix.gox: internal/syscall/unix.lo
$(BUILDGOX)
internal/testenv.gox: internal/testenv.lo
$(BUILDGOX)
internal/trace.gox: internal/trace.lo
$(BUILDGOX)
io/ioutil.gox: io/ioutil.lo io/ioutil.gox: io/ioutil.lo
$(BUILDGOX) $(BUILDGOX)
@ -3674,6 +4029,8 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo mime/multipart.gox: mime/multipart.lo
$(BUILDGOX) $(BUILDGOX)
mime/quotedprintable.gox: mime/quotedprintable.lo
$(BUILDGOX)
net/http.gox: net/http.lo net/http.gox: net/http.lo
$(BUILDGOX) $(BUILDGOX)
@ -3704,6 +4061,9 @@ net/http/pprof.gox: net/http/pprof.lo
net/http/internal.gox: net/http/internal.lo net/http/internal.gox: net/http/internal.lo
$(BUILDGOX) $(BUILDGOX)
net/internal/socktest.gox: net/internal/socktest.lo
$(BUILDGOX)
net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
$(BUILDGOX) $(BUILDGOX)
@ -3733,9 +4093,6 @@ runtime/pprof.gox: runtime/pprof.lo
sync/atomic.gox: sync/atomic.lo sync/atomic.gox: sync/atomic.lo
$(BUILDGOX) $(BUILDGOX)
internal/syscall.gox: internal/syscall.lo
$(BUILDGOX)
text/scanner.gox: text/scanner.lo text/scanner.gox: text/scanner.lo
$(BUILDGOX) $(BUILDGOX)
text/tabwriter.gox: text/tabwriter.lo text/tabwriter.gox: text/tabwriter.lo
@ -3830,13 +4187,17 @@ TEST_PACKAGES = \
exp/terminal/check \ exp/terminal/check \
html/template/check \ html/template/check \
go/ast/check \ go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \ go/build/check \
go/constant/check \
go/doc/check \ go/doc/check \
go/format/check \ go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
go/parser/check \ go/parser/check \
go/printer/check \ go/printer/check \
go/scanner/check \ go/scanner/check \
go/token/check \ go/token/check \
go/types/check \
hash/adler32/check \ hash/adler32/check \
hash/crc32/check \ hash/crc32/check \
hash/crc64/check \ hash/crc64/check \
@ -3846,12 +4207,15 @@ TEST_PACKAGES = \
image/jpeg/check \ image/jpeg/check \
image/png/check \ image/png/check \
index/suffixarray/check \ index/suffixarray/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \ io/ioutil/check \
log/syslog/check \ log/syslog/check \
math/big/check \ math/big/check \
math/cmplx/check \ math/cmplx/check \
math/rand/check \ math/rand/check \
mime/multipart/check \ mime/multipart/check \
mime/quotedprintable/check \
net/http/check \ net/http/check \
net/http/cgi/check \ net/http/cgi/check \
net/http/cookiejar/check \ net/http/cookiejar/check \
@ -3859,6 +4223,7 @@ TEST_PACKAGES = \
net/http/httptest/check \ net/http/httptest/check \
net/http/httputil/check \ net/http/httputil/check \
net/http/internal/check \ net/http/internal/check \
net/internal/socktest/check \
net/mail/check \ net/mail/check \
net/rpc/check \ net/rpc/check \
net/smtp/check \ net/smtp/check \

View File

@ -196,16 +196,21 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
encoding/binary.lo encoding/csv.lo encoding/gob.lo \ encoding/binary.lo encoding/csv.lo encoding/gob.lo \
encoding/hex.lo encoding/json.lo encoding/pem.lo \ encoding/hex.lo encoding/json.lo encoding/pem.lo \
encoding/xml.lo exp/proxy.lo exp/terminal.lo html/template.lo \ encoding/xml.lo exp/proxy.lo exp/terminal.lo html/template.lo \
go/ast.lo go/build.lo go/doc.lo go/format.lo go/parser.lo \ go/ast.lo go/build.lo go/constant.lo go/doc.lo go/format.lo \
go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \ go/importer.lo go/internal/gcimporter.lo \
go/internal/gccgoimporter.lo go/parser.lo go/printer.lo \
go/scanner.lo go/token.lo go/types.lo hash/adler32.lo \
hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \ hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \ net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \
net/http/httputil.lo net/http/internal.lo net/http/pprof.lo \ net/http/httputil.lo net/http/internal.lo net/http/pprof.lo \
image/color.lo image/color/palette.lo image/draw.lo \ image/color.lo image/color/palette.lo image/draw.lo \
image/gif.lo image/jpeg.lo image/png.lo index/suffixarray.lo \ image/gif.lo image/internal/imageutil.lo image/jpeg.lo \
internal/syscall.lo io/ioutil.lo log/syslog.lo \ image/png.lo index/suffixarray.lo internal/format.lo \
log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \ internal/singleflight.lo internal/syscall/unix.lo \
mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \ internal/testenv.lo internal/trace.lo io/ioutil.lo \
log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
math/rand.lo mime/multipart.lo mime/quotedprintable.lo \
net/http.lo net/internal/socktest.lo net/mail.lo net/rpc.lo \
net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \ net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \
old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \ old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \
os/user.lo path/filepath.lo regexp/syntax.lo \ os/user.lo path/filepath.lo regexp/syntax.lo \
@ -681,12 +686,15 @@ toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \ toolexeclibgogo_DATA = \
go/ast.gox \ go/ast.gox \
go/build.gox \ go/build.gox \
go/constant.gox \
go/doc.gox \ go/doc.gox \
go/format.gox \ go/format.gox \
go/importer.gox \
go/parser.gox \ go/parser.gox \
go/printer.gox \ go/printer.gox \
go/scanner.gox \ go/scanner.gox \
go/token.gox go/token.gox \
go/types.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash toolexeclibgohashdir = $(toolexeclibgodir)/hash
toolexeclibgohash_DATA = \ toolexeclibgohash_DATA = \
@ -731,7 +739,8 @@ toolexeclibgomath_DATA = \
toolexeclibgomimedir = $(toolexeclibgodir)/mime toolexeclibgomimedir = $(toolexeclibgodir)/mime
toolexeclibgomime_DATA = \ toolexeclibgomime_DATA = \
mime/multipart.gox mime/multipart.gox \
mime/quotedprintable.gox
toolexeclibgonetdir = $(toolexeclibgodir)/net toolexeclibgonetdir = $(toolexeclibgodir)/net
toolexeclibgonet_DATA = \ toolexeclibgonet_DATA = \
@ -1023,16 +1032,22 @@ go_math_files = \
go/math/tanh.go \ go/math/tanh.go \
go/math/unsafe.go go/math/unsafe.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file =
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file = go/mime/type_dragonfly.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file = go/mime/type_freebsd.go
@LIBGO_IS_OPENBSD_TRUE@go_mime_type_file = go/mime/type_openbsd.go
go_mime_files = \ go_mime_files = \
go/mime/encodedword.go \
go/mime/grammar.go \ go/mime/grammar.go \
go/mime/mediatype.go \ go/mime/mediatype.go \
go/mime/type.go \ go/mime/type.go \
go/mime/type_unix.go go/mime/type_unix.go \
$(go_mime_type_file)
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_linux.go @LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_solaris.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_linux.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go @LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
@ -1053,7 +1068,20 @@ go_mime_files = \
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_stub.go @LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_stub.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go @LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resold.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resold.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sendfile_file = go/net/sendfile_solaris.go
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go @LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go @LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
@ -1069,15 +1097,22 @@ go_mime_files = \
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
@LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go @LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
go_net_common_files = \ go_net_common_files = \
go/net/addrselect.go \
$(go_net_cloexec_file) \ $(go_net_cloexec_file) \
go/net/conf.go \
go/net/dial.go \ go/net/dial.go \
go/net/dnsclient.go \ go/net/dnsclient.go \
go/net/dnsclient_unix.go \ go/net/dnsclient_unix.go \
go/net/dnsconfig_unix.go \ go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \ go/net/dnsmsg.go \
go/net/fd_mutex.go \ go/net/fd_mutex.go \
go/net/fd_posix.go \
go/net/fd_unix.go \ go/net/fd_unix.go \
go/net/file.go \
go/net/file_unix.go \ go/net/file_unix.go \
go/net/hook.go \
go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \ go/net/hosts.go \
go/net/interface.go \ go/net/interface.go \
$(go_net_interface_file) \ $(go_net_interface_file) \
@ -1090,6 +1125,7 @@ go_net_common_files = \
go/net/lookup_unix.go \ go/net/lookup_unix.go \
go/net/mac.go \ go/net/mac.go \
go/net/net.go \ go/net/net.go \
go/net/nss.go \
go/net/parse.go \ go/net/parse.go \
go/net/pipe.go \ go/net/pipe.go \
go/net/fd_poll_runtime.go \ go/net/fd_poll_runtime.go \
@ -1097,7 +1133,6 @@ go_net_common_files = \
go/net/port_unix.go \ go/net/port_unix.go \
go/net/race0.go \ go/net/race0.go \
$(go_net_sendfile_file) \ $(go_net_sendfile_file) \
go/net/singleflight.go \
go/net/sock_posix.go \ go/net/sock_posix.go \
$(go_net_sock_file) \ $(go_net_sock_file) \
go/net/sockopt_posix.go \ go/net/sockopt_posix.go \
@ -1115,6 +1150,8 @@ go_net_common_files = \
go_net_files = \ go_net_files = \
go/net/cgo_unix.go \ go/net/cgo_unix.go \
$(go_net_cgo_file) \ $(go_net_cgo_file) \
$(go_net_cgo_res_file) \
$(go_net_cgo_sock_file) \
$(go_net_common_files) $(go_net_common_files)
go_netgo_files = \ go_netgo_files = \
@ -1147,6 +1184,13 @@ go_netgo_files = \
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atim.go @LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atim.go
@LIBGO_IS_LINUX_FALSE@go_os_pipe_file = go/os/pipe_bsd.go @LIBGO_IS_LINUX_FALSE@go_os_pipe_file = go/os/pipe_bsd.go
@LIBGO_IS_LINUX_TRUE@go_os_pipe_file = go/os/pipe_linux.go @LIBGO_IS_LINUX_TRUE@go_os_pipe_file = go/os/pipe_linux.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sticky_file = go/os/sticky_notbsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
go_os_files = \ go_os_files = \
$(go_os_dir_file) \ $(go_os_dir_file) \
go/os/dir.go \ go/os/dir.go \
@ -1167,6 +1211,7 @@ go_os_files = \
$(go_os_pipe_file) \ $(go_os_pipe_file) \
go/os/proc.go \ go/os/proc.go \
$(go_os_stat_file) \ $(go_os_stat_file) \
$(go_os_sticky_file) \
go/os/str.go \ go/os/str.go \
$(go_os_sys_file) \ $(go_os_sys_file) \
$(go_os_cloexec_file) \ $(go_os_cloexec_file) \
@ -1188,6 +1233,7 @@ go_reflect_makefunc_c_file = \
go/reflect/makefunc_ffi_c.c go/reflect/makefunc_ffi_c.c
go_regexp_files = \ go_regexp_files = \
go/regexp/backtrack.go \
go/regexp/exec.go \ go/regexp/exec.go \
go/regexp/onepass.go \ go/regexp/onepass.go \
go/regexp/regexp.go go/regexp/regexp.go
@ -1203,7 +1249,6 @@ go_runtime_files = \
go/runtime/error.go \ go/runtime/error.go \
go/runtime/extern.go \ go/runtime/extern.go \
go/runtime/mem.go \ go/runtime/mem.go \
go/runtime/softfloat64.go \
version.go version.go
noinst_DATA = zstdpkglist.go noinst_DATA = zstdpkglist.go
@ -1216,6 +1261,7 @@ go_strconv_files = \
go/strconv/atof.go \ go/strconv/atof.go \
go/strconv/atoi.go \ go/strconv/atoi.go \
go/strconv/decimal.go \ go/strconv/decimal.go \
go/strconv/doc.go \
go/strconv/extfloat.go \ go/strconv/extfloat.go \
go/strconv/ftoa.go \ go/strconv/ftoa.go \
go/strconv/isprint.go \ go/strconv/isprint.go \
@ -1223,6 +1269,7 @@ go_strconv_files = \
go/strconv/quote.go go/strconv/quote.go
go_strings_files = \ go_strings_files = \
go/strings/compare.go \
go/strings/reader.go \ go/strings/reader.go \
go/strings/replace.go \ go/strings/replace.go \
go/strings/search.go \ go/strings/search.go \
@ -1246,6 +1293,7 @@ go_sync_files = \
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/log/syslog/syslog_libc.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/log/syslog/syslog_libc.go
@LIBGO_IS_SOLARIS_TRUE@go_syslog_file = go/log/syslog/syslog_libc.go @LIBGO_IS_SOLARIS_TRUE@go_syslog_file = go/log/syslog/syslog_libc.go
go_log_syslog_files = \ go_log_syslog_files = \
go/log/syslog/doc.go \
go/log/syslog/syslog.go \ go/log/syslog/syslog.go \
$(go_syslog_file) $(go_syslog_file)
@ -1375,6 +1423,7 @@ go_crypto_md5_files = \
@LIBGO_IS_LINUX_FALSE@crypto_rand_file = @LIBGO_IS_LINUX_FALSE@crypto_rand_file =
@LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go @LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go
go_crypto_rand_files = \ go_crypto_rand_files = \
go/crypto/rand/eagain.go \
go/crypto/rand/rand.go \ go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \ go/crypto/rand/rand_unix.go \
$(crypto_rand_file) \ $(crypto_rand_file) \
@ -1418,6 +1467,14 @@ go_crypto_tls_files = \
go/crypto/tls/ticket.go \ go/crypto/tls/ticket.go \
go/crypto/tls/tls.go go/crypto/tls/tls.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file =
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_darwin.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_crypto_x509_root_file = go/crypto/x509/root_solaris.go
@LIBGO_IS_LINUX_TRUE@go_crypto_x509_root_file = go/crypto/x509/root_linux.go
go_crypto_x509_files = \ go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \ go/crypto/x509/cert_pool.go \
go/crypto/x509/pem_decrypt.go \ go/crypto/x509/pem_decrypt.go \
@ -1425,6 +1482,7 @@ go_crypto_x509_files = \
go/crypto/x509/pkcs8.go \ go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \ go/crypto/x509/root.go \
go/crypto/x509/root_unix.go \ go/crypto/x509/root_unix.go \
$(go_crypto_x509_root_file) \
go/crypto/x509/sec1.go \ go/crypto/x509/sec1.go \
go/crypto/x509/verify.go \ go/crypto/x509/verify.go \
go/crypto/x509/x509.go go/crypto/x509/x509.go
@ -1442,6 +1500,7 @@ go_database_sql_driver_files = \
go_debug_dwarf_files = \ go_debug_dwarf_files = \
go/debug/dwarf/buf.go \ go/debug/dwarf/buf.go \
go/debug/dwarf/class_string.go \
go/debug/dwarf/const.go \ go/debug/dwarf/const.go \
go/debug/dwarf/entry.go \ go/debug/dwarf/entry.go \
go/debug/dwarf/line.go \ go/debug/dwarf/line.go \
@ -1551,6 +1610,10 @@ go_go_build_files = \
go/go/build/read.go \ go/go/build/read.go \
go/go/build/syslist.go go/go/build/syslist.go
go_go_constant_files = \
go/go/constant/go14.go \
go/go/constant/value.go
go_go_doc_files = \ go_go_doc_files = \
go/go/doc/comment.go \ go/go/doc/comment.go \
go/go/doc/doc.go \ go/go/doc/doc.go \
@ -1563,6 +1626,9 @@ go_go_doc_files = \
go_go_format_files = \ go_go_format_files = \
go/go/format/format.go go/go/format/format.go
go_go_importer_files = \
go/go/importer/importer.go
go_go_parser_files = \ go_go_parser_files = \
go/go/parser/interface.go \ go/go/parser/interface.go \
go/go/parser/parser.go go/go/parser/parser.go
@ -1580,6 +1646,49 @@ go_go_token_files = \
go/go/token/serialize.go \ go/go/token/serialize.go \
go/go/token/token.go go/go/token/token.go
go_go_types_files = \
go/go/types/api.go \
go/go/types/assignments.go \
go/go/types/builtins.go \
go/go/types/call.go \
go/go/types/check.go \
go/go/types/conversions.go \
go/go/types/decl.go \
go/go/types/errors.go \
go/go/types/eval.go \
go/go/types/expr.go \
go/go/types/exprstring.go \
go/go/types/go12.go \
go/go/types/initorder.go \
go/go/types/labels.go \
go/go/types/lookup.go \
go/go/types/methodset.go \
go/go/types/object.go \
go/go/types/objset.go \
go/go/types/operand.go \
go/go/types/ordering.go \
go/go/types/package.go \
go/go/types/predicates.go \
go/go/types/resolver.go \
go/go/types/return.go \
go/go/types/scope.go \
go/go/types/selection.go \
go/go/types/stmt.go \
go/go/types/sizes.go \
go/go/types/type.go \
go/go/types/typestring.go \
go/go/types/typexpr.go \
go/go/types/universe.go
go_go_internal_gcimporter_files = \
go/go/internal/gcimporter/exportdata.go \
go/go/internal/gcimporter/gcimporter.go
go_go_internal_gccgoimporter_files = \
go/go/internal/gccgoimporter/gccgoinstallation.go \
go/go/internal/gccgoimporter/importer.go \
go/go/internal/gccgoimporter/parser.go
go_hash_adler32_files = \ go_hash_adler32_files = \
go/hash/adler32/adler32.go go/hash/adler32/adler32.go
@ -1621,6 +1730,10 @@ go_image_gif_files = \
go/image/gif/reader.go \ go/image/gif/reader.go \
go/image/gif/writer.go go/image/gif/writer.go
go_image_internal_imageutil_files = \
go/image/internal/imageutil/imageutil.go \
go/image/internal/imageutil/impl.go
go_image_jpeg_files = \ go_image_jpeg_files = \
go/image/jpeg/fdct.go \ go/image/jpeg/fdct.go \
go/image/jpeg/huffman.go \ go/image/jpeg/huffman.go \
@ -1638,15 +1751,44 @@ go_index_suffixarray_files = \
go/index/suffixarray/qsufsort.go \ go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go go/index/suffixarray/suffixarray.go
go_internal_format_files = \
go/internal/format/format.go
go_internal_singleflight_files = \
go/internal/singleflight/singleflight.go
@LIBGO_IS_LINUX_FALSE@internal_syscall_unix_getrandom_file =
@LIBGO_IS_LINUX_TRUE@internal_syscall_unix_getrandom_file = go/internal/syscall/unix/getrandom_linux.go
go_internal_syscall_unix_files = \
go/internal/syscall/unix/dummy.go \
$(internal_syscall_unix_getrandom_file)
go_internal_testenv_files = \
go/internal/testenv/testenv.go
go_internal_trace_files = \
go/internal/trace/goroutines.go \
go/internal/trace/parser.go
go_io_ioutil_files = \ go_io_ioutil_files = \
go/io/ioutil/ioutil.go \ go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go go/io/ioutil/tempfile.go
go_math_big_files = \ go_math_big_files = \
go/math/big/accuracy_string.go \
go/math/big/arith.go \ go/math/big/arith.go \
go/math/big/arith_decl_pure.go \
go/math/big/decimal.go \
go/math/big/float.go \
go/math/big/floatconv.go \
go/math/big/ftoa.go \
go/math/big/int.go \ go/math/big/int.go \
go/math/big/intconv.go \
go/math/big/nat.go \ go/math/big/nat.go \
go/math/big/rat.go go/math/big/natconv.go \
go/math/big/rat.go \
go/math/big/ratconv.go \
go/math/big/roundingmode_string.go
go_math_cmplx_files = \ go_math_cmplx_files = \
go/math/cmplx/abs.go \ go/math/cmplx/abs.go \
@ -1674,9 +1816,12 @@ go_math_rand_files = \
go_mime_multipart_files = \ go_mime_multipart_files = \
go/mime/multipart/formdata.go \ go/mime/multipart/formdata.go \
go/mime/multipart/multipart.go \ go/mime/multipart/multipart.go \
go/mime/multipart/quotedprintable.go \
go/mime/multipart/writer.go go/mime/multipart/writer.go
go_mime_quotedprintable_files = \
go/mime/quotedprintable/reader.go \
go/mime/quotedprintable/writer.go
go_net_http_files = \ go_net_http_files = \
go/net/http/client.go \ go/net/http/client.go \
go/net/http/cookie.go \ go/net/http/cookie.go \
@ -1738,6 +1883,16 @@ go_net_http_httputil_files = \
go_net_http_internal_files = \ go_net_http_internal_files = \
go/net/http/internal/chunked.go go/net/http/internal/chunked.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_internal_socktest_sys =
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
@LIBGO_IS_LINUX_TRUE@go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
go_net_internal_socktest_files = \
go/net/internal/socktest/switch.go \
go/net/internal/socktest/switch_posix.go \
go/net/internal/socktest/switch_unix.go \
go/net/internal/socktest/sys_unix.go \
$(go_net_internal_socktest_sys)
go_old_regexp_files = \ go_old_regexp_files = \
go/old/regexp/regexp.go go/old/regexp/regexp.go
@ -1749,6 +1904,7 @@ go_old_template_files = \
go_os_exec_files = \ go_os_exec_files = \
go/os/exec/exec.go \ go/os/exec/exec.go \
go/os/exec/exec_posix.go \
go/os/exec/lp_unix.go go/os/exec/lp_unix.go
go_os_signal_files = \ go_os_signal_files = \
@ -1798,6 +1954,7 @@ go_text_template_files = \
go/text/template/exec.go \ go/text/template/exec.go \
go/text/template/funcs.go \ go/text/template/funcs.go \
go/text/template/helper.go \ go/text/template/helper.go \
go/text/template/option.go \
go/text/template/template.go go/text/template/template.go
go_text_template_parse_files = \ go_text_template_parse_files = \
@ -1917,6 +2074,8 @@ go_unicode_utf8_files = \
# Test files. # Test files.
@LIBGO_IS_LINUX_TRUE@syscall_creds_test_file = go/syscall/creds_test.go @LIBGO_IS_LINUX_TRUE@syscall_creds_test_file = go/syscall/creds_test.go
@LIBGO_IS_LINUX_FALSE@syscall_exec_test_file =
@LIBGO_IS_LINUX_TRUE@syscall_exec_test_file = go/syscall/exec_linux_test.go go/syscall/syscall_linux_test.go
go_base_syscall_files = \ go_base_syscall_files = \
go/syscall/env_unix.go \ go/syscall/env_unix.go \
go/syscall/syscall_errno.go \ go/syscall/syscall_errno.go \
@ -1961,17 +2120,14 @@ go_syscall_c_files = \
go_syscall_test_files = \ go_syscall_test_files = \
$(syscall_creds_test_file) \ $(syscall_creds_test_file) \
$(syscall_exec_test_file) \
go/syscall/exec_unix_test.go \
go/syscall/export_test.go \ go/syscall/export_test.go \
go/syscall/export_unix_test.go \
go/syscall/mmap_unix_test.go \ go/syscall/mmap_unix_test.go \
go/syscall/syscall_test.go \ go/syscall/syscall_test.go \
go/syscall/syscall_unix_test.go go/syscall/syscall_unix_test.go
@LIBGO_IS_LINUX_FALSE@internal_syscall_getrandom_file =
@LIBGO_IS_LINUX_TRUE@internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go
go_internal_syscall_files = \
go/internal/syscall/dummy.go \
$(internal_syscall_getrandom_file)
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo = @LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
# os_lib_inotify_lo = os/inotify.lo # os_lib_inotify_lo = os/inotify.lo
@ -2064,12 +2220,17 @@ libgo_go_objs = \
html/template.lo \ html/template.lo \
go/ast.lo \ go/ast.lo \
go/build.lo \ go/build.lo \
go/constant.lo \
go/doc.lo \ go/doc.lo \
go/format.lo \ go/format.lo \
go/importer.lo \
go/internal/gcimporter.lo \
go/internal/gccgoimporter.lo \
go/parser.lo \ go/parser.lo \
go/printer.lo \ go/printer.lo \
go/scanner.lo \ go/scanner.lo \
go/token.lo \ go/token.lo \
go/types.lo \
hash/adler32.lo \ hash/adler32.lo \
hash/crc32.lo \ hash/crc32.lo \
hash/crc64.lo \ hash/crc64.lo \
@ -2085,10 +2246,15 @@ libgo_go_objs = \
image/color/palette.lo \ image/color/palette.lo \
image/draw.lo \ image/draw.lo \
image/gif.lo \ image/gif.lo \
image/internal/imageutil.lo \
image/jpeg.lo \ image/jpeg.lo \
image/png.lo \ image/png.lo \
index/suffixarray.lo \ index/suffixarray.lo \
internal/syscall.lo \ internal/format.lo \
internal/singleflight.lo \
internal/syscall/unix.lo \
internal/testenv.lo \
internal/trace.lo \
io/ioutil.lo \ io/ioutil.lo \
log/syslog.lo \ log/syslog.lo \
log/syslog/syslog_c.lo \ log/syslog/syslog_c.lo \
@ -2096,7 +2262,9 @@ libgo_go_objs = \
math/cmplx.lo \ math/cmplx.lo \
math/rand.lo \ math/rand.lo \
mime/multipart.lo \ mime/multipart.lo \
mime/quotedprintable.lo \
net/http.lo \ net/http.lo \
net/internal/socktest.lo \
net/mail.lo \ net/mail.lo \
net/rpc.lo \ net/rpc.lo \
net/smtp.lo \ net/smtp.lo \
@ -2203,11 +2371,11 @@ CHECK = \
$(MKDIR_P) $(@D); \ $(MKDIR_P) $(@D); \
rm -f $@-testsum $@-testlog; \ rm -f $@-testsum $@-testlog; \
if test "$(USE_DEJAGNU)" = "yes"; then \ if test "$(USE_DEJAGNU)" = "yes"; then \
$(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
elif test "$(GOBENCH)" != ""; then \ elif test "$(GOBENCH)" != ""; then \
$(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
else \ else \
if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \ if $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
echo "PASS: $(@D)" >> $@-testlog; \ echo "PASS: $(@D)" >> $@-testlog; \
echo "PASS: $(@D)"; \ echo "PASS: $(@D)"; \
echo "PASS: $(@D)" > $@-testsum; \ echo "PASS: $(@D)" > $@-testsum; \
@ -2320,13 +2488,17 @@ TEST_PACKAGES = \
exp/terminal/check \ exp/terminal/check \
html/template/check \ html/template/check \
go/ast/check \ go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \ go/build/check \
go/constant/check \
go/doc/check \ go/doc/check \
go/format/check \ go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
go/parser/check \ go/parser/check \
go/printer/check \ go/printer/check \
go/scanner/check \ go/scanner/check \
go/token/check \ go/token/check \
go/types/check \
hash/adler32/check \ hash/adler32/check \
hash/crc32/check \ hash/crc32/check \
hash/crc64/check \ hash/crc64/check \
@ -2336,12 +2508,15 @@ TEST_PACKAGES = \
image/jpeg/check \ image/jpeg/check \
image/png/check \ image/png/check \
index/suffixarray/check \ index/suffixarray/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \ io/ioutil/check \
log/syslog/check \ log/syslog/check \
math/big/check \ math/big/check \
math/cmplx/check \ math/cmplx/check \
math/rand/check \ math/rand/check \
mime/multipart/check \ mime/multipart/check \
mime/quotedprintable/check \
net/http/check \ net/http/check \
net/http/cgi/check \ net/http/cgi/check \
net/http/cookiejar/check \ net/http/cookiejar/check \
@ -2349,6 +2524,7 @@ TEST_PACKAGES = \
net/http/httptest/check \ net/http/httptest/check \
net/http/httputil/check \ net/http/httputil/check \
net/http/internal/check \ net/http/internal/check \
net/internal/socktest/check \
net/mail/check \ net/mail/check \
net/rpc/check \ net/rpc/check \
net/smtp/check \ net/smtp/check \
@ -5357,6 +5533,15 @@ go/build/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/build/check .PHONY: go/build/check
@go_include@ go/constant.lo.dep
go/constant.lo.dep: $(go_go_constant_files)
$(BUILDDEPS)
go/constant.lo: $(go_go_constant_files)
$(BUILDPACKAGE)
go/constant/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/constant/check
@go_include@ go/doc.lo.dep @go_include@ go/doc.lo.dep
go/doc.lo.dep: $(go_go_doc_files) go/doc.lo.dep: $(go_go_doc_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5375,6 +5560,15 @@ go/format/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/format/check .PHONY: go/format/check
@go_include@ go/importer.lo.dep
go/importer.lo.dep: $(go_go_importer_files)
$(BUILDDEPS)
go/importer.lo: $(go_go_importer_files)
$(BUILDPACKAGE)
go/importer/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/importer/check
@go_include@ go/parser.lo.dep @go_include@ go/parser.lo.dep
go/parser.lo.dep: $(go_go_parser_files) go/parser.lo.dep: $(go_go_parser_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5411,6 +5605,33 @@ go/token/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: go/token/check .PHONY: go/token/check
@go_include@ go/types.lo.dep
go/types.lo.dep: $(go_go_types_files)
$(BUILDDEPS)
go/types.lo: $(go_go_types_files)
$(BUILDPACKAGE)
go/types/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/types/check
@go_include@ go/internal/gcimporter.lo.dep
go/internal/gcimporter.lo.dep: $(go_go_internal_gcimporter_files)
$(BUILDDEPS)
go/internal/gcimporter.lo: $(go_go_internal_gcimporter_files)
$(BUILDPACKAGE)
go/internal/gcimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gcimporter/check
@go_include@ go/internal/gccgoimporter.lo.dep
go/internal/gccgoimporter.lo.dep: $(go_go_internal_gccgoimporter_files)
$(BUILDDEPS)
go/internal/gccgoimporter.lo: $(go_go_internal_gccgoimporter_files)
$(BUILDPACKAGE)
go/internal/gccgoimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gccgoimporter/check
@go_include@ hash/adler32.lo.dep @go_include@ hash/adler32.lo.dep
hash/adler32.lo.dep: $(go_hash_adler32_files) hash/adler32.lo.dep: $(go_hash_adler32_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5483,6 +5704,15 @@ image/gif/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: image/gif/check .PHONY: image/gif/check
@go_include@ image/internal/imageutil.lo.dep
image/internal/imageutil.lo.dep: $(go_image_internal_imageutil_files)
$(BUILDDEPS)
image/internal/imageutil.lo: $(go_image_internal_imageutil_files)
$(BUILDPACKAGE)
image/internal/imageutil/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/internal/imageutil/check
@go_include@ image/jpeg.lo.dep @go_include@ image/jpeg.lo.dep
image/jpeg.lo.dep: $(go_image_jpeg_files) image/jpeg.lo.dep: $(go_image_jpeg_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5510,6 +5740,51 @@ index/suffixarray/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: index/suffixarray/check .PHONY: index/suffixarray/check
@go_include@ internal/format.lo.dep
internal/format.lo.dep: $(go_internal_format_files)
$(BUILDDEPS)
internal/format.lo: $(go_internal_format_files)
$(BUILDPACKAGE)
internal/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/format/check
@go_include@ internal/singleflight.lo.dep
internal/singleflight.lo.dep: $(go_internal_singleflight_files)
$(BUILDDEPS)
internal/singleflight.lo: $(go_internal_singleflight_files)
$(BUILDPACKAGE)
internal/singleflight/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/singleflight/check
@go_include@ internal/syscall/unix.lo.dep
internal/syscall/unix.lo.dep: $(go_internal_syscall_unix_files)
$(BUILDDEPS)
internal/syscall/unix.lo: $(go_internal_syscall_unix_files)
$(BUILDPACKAGE)
internal/syscall/unix/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/unix/check
@go_include@ internal/testenv.lo.dep
internal/testenv.lo.dep: $(go_internal_testenv_files)
$(BUILDDEPS)
internal/testenv.lo: $(go_internal_testenv_files)
$(BUILDPACKAGE)
internal/testenv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/testenv/check
@go_include@ internal/trace.lo.dep
internal/trace.lo.dep: $(go_internal_trace_files)
$(BUILDDEPS)
internal/trace.lo: $(go_internal_trace_files)
$(BUILDPACKAGE)
internal/trace/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/trace/check
@go_include@ io/ioutil.lo.dep @go_include@ io/ioutil.lo.dep
io/ioutil.lo.dep: $(go_io_ioutil_files) io/ioutil.lo.dep: $(go_io_ioutil_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5567,6 +5842,15 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: mime/multipart/check .PHONY: mime/multipart/check
@go_include@ mime/quotedprintable.lo.dep
mime/quotedprintable.lo.dep: $(go_mime_quotedprintable_files)
$(BUILDDEPS)
mime/quotedprintable.lo: $(go_mime_quotedprintable_files)
$(BUILDPACKAGE)
mime/quotedprintable/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/quotedprintable/check
@go_include@ net/http.lo.dep @go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files) net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5684,6 +5968,15 @@ net/http/pprof/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: net/http/pprof/check .PHONY: net/http/pprof/check
@go_include@ net/internal/socktest.lo.dep
net/internal/socktest.lo.dep: $(go_net_internal_socktest_files)
$(BUILDDEPS)
net/internal/socktest.lo: $(go_net_internal_socktest_files)
$(BUILDPACKAGE)
net/internal/socktest/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/internal/socktest/check
@go_include@ net/rpc/jsonrpc.lo.dep @go_include@ net/rpc/jsonrpc.lo.dep
net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files) net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
$(BUILDDEPS) $(BUILDDEPS)
@ -5875,15 +6168,6 @@ syscall/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: syscall/check .PHONY: syscall/check
@go_include@ internal/syscall.lo.dep
internal/syscall.lo.dep: $(go_internal_syscall_files)
$(BUILDDEPS)
internal/syscall.lo: $(go_internal_syscall_files)
$(BUILDPACKAGE)
internal/syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/check
bufio.gox: bufio.lo bufio.gox: bufio.lo
$(BUILDGOX) $(BUILDGOX)
bytes.gox: bytes.lo bytes.gox: bytes.lo
@ -6058,10 +6342,14 @@ go/ast.gox: go/ast.lo
$(BUILDGOX) $(BUILDGOX)
go/build.gox: go/build.lo go/build.gox: go/build.lo
$(BUILDGOX) $(BUILDGOX)
go/constant.gox: go/constant.lo
$(BUILDGOX)
go/doc.gox: go/doc.lo go/doc.gox: go/doc.lo
$(BUILDGOX) $(BUILDGOX)
go/format.gox: go/format.lo go/format.gox: go/format.lo
$(BUILDGOX) $(BUILDGOX)
go/importer.gox: go/importer.lo
$(BUILDGOX)
go/parser.gox: go/parser.lo go/parser.gox: go/parser.lo
$(BUILDGOX) $(BUILDGOX)
go/printer.gox: go/printer.lo go/printer.gox: go/printer.lo
@ -6070,6 +6358,13 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX) $(BUILDGOX)
go/token.gox: go/token.lo go/token.gox: go/token.lo
$(BUILDGOX) $(BUILDGOX)
go/types.gox: go/types.lo
$(BUILDGOX)
go/internal/gcimporter.gox: go/internal/gcimporter.lo
$(BUILDGOX)
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
$(BUILDGOX)
hash/adler32.gox: hash/adler32.lo hash/adler32.gox: hash/adler32.lo
$(BUILDGOX) $(BUILDGOX)
@ -6086,6 +6381,8 @@ image/draw.gox: image/draw.lo
$(BUILDGOX) $(BUILDGOX)
image/gif.gox: image/gif.lo image/gif.gox: image/gif.lo
$(BUILDGOX) $(BUILDGOX)
image/internal/imageutil.gox: image/internal/imageutil.lo
$(BUILDGOX)
image/jpeg.gox: image/jpeg.lo image/jpeg.gox: image/jpeg.lo
$(BUILDGOX) $(BUILDGOX)
image/png.gox: image/png.lo image/png.gox: image/png.lo
@ -6097,6 +6394,17 @@ image/color/palette.gox: image/color/palette.lo
index/suffixarray.gox: index/suffixarray.lo index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX) $(BUILDGOX)
internal/format.gox: internal/format.lo
$(BUILDGOX)
internal/singleflight.gox: internal/singleflight.lo
$(BUILDGOX)
internal/syscall/unix.gox: internal/syscall/unix.lo
$(BUILDGOX)
internal/testenv.gox: internal/testenv.lo
$(BUILDGOX)
internal/trace.gox: internal/trace.lo
$(BUILDGOX)
io/ioutil.gox: io/ioutil.lo io/ioutil.gox: io/ioutil.lo
$(BUILDGOX) $(BUILDGOX)
@ -6112,6 +6420,8 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo mime/multipart.gox: mime/multipart.lo
$(BUILDGOX) $(BUILDGOX)
mime/quotedprintable.gox: mime/quotedprintable.lo
$(BUILDGOX)
net/http.gox: net/http.lo net/http.gox: net/http.lo
$(BUILDGOX) $(BUILDGOX)
@ -6142,6 +6452,9 @@ net/http/pprof.gox: net/http/pprof.lo
net/http/internal.gox: net/http/internal.lo net/http/internal.gox: net/http/internal.lo
$(BUILDGOX) $(BUILDGOX)
net/internal/socktest.gox: net/internal/socktest.lo
$(BUILDGOX)
net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
$(BUILDGOX) $(BUILDGOX)
@ -6171,9 +6484,6 @@ runtime/pprof.gox: runtime/pprof.lo
sync/atomic.gox: sync/atomic.lo sync/atomic.gox: sync/atomic.lo
$(BUILDGOX) $(BUILDGOX)
internal/syscall.gox: internal/syscall.lo
$(BUILDGOX)
text/scanner.gox: text/scanner.lo text/scanner.gox: text/scanner.lo
$(BUILDGOX) $(BUILDGOX)
text/tabwriter.gox: text/tabwriter.lo text/tabwriter.gox: text/tabwriter.lo

View File

@ -1 +1 @@
go1.4.2 go1.5

View File

@ -139,8 +139,8 @@ func (fi headerFileInfo) Mode() (mode os.FileMode) {
} }
switch fi.h.Typeflag { switch fi.h.Typeflag {
case TypeLink, TypeSymlink: case TypeSymlink:
// hard link, symbolic link // symbolic link
mode |= os.ModeSymlink mode |= os.ModeSymlink
case TypeChar: case TypeChar:
// character device node // character device node
@ -249,6 +249,30 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
if fm&os.ModeSticky != 0 { if fm&os.ModeSticky != 0 {
h.Mode |= c_ISVTX h.Mode |= c_ISVTX
} }
// If possible, populate additional fields from OS-specific
// FileInfo fields.
if sys, ok := fi.Sys().(*Header); ok {
// This FileInfo came from a Header (not the OS). Use the
// original Header to populate all remaining fields.
h.Uid = sys.Uid
h.Gid = sys.Gid
h.Uname = sys.Uname
h.Gname = sys.Gname
h.AccessTime = sys.AccessTime
h.ChangeTime = sys.ChangeTime
if sys.Xattrs != nil {
h.Xattrs = make(map[string]string)
for k, v := range sys.Xattrs {
h.Xattrs[k] = v
}
}
if sys.Typeflag == TypeLink {
// hard link
h.Typeflag = TypeLink
h.Size = 0
h.Linkname = sys.Linkname
}
}
if sysStat != nil { if sysStat != nil {
return h, sysStat(fi, h) return h, sysStat(fi, h)
} }

View File

@ -85,6 +85,8 @@ const (
func NewReader(r io.Reader) *Reader { return &Reader{r: r} } func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
// Next advances to the next entry in the tar archive. // Next advances to the next entry in the tar archive.
//
// io.EOF is returned at the end of the input.
func (tr *Reader) Next() (*Header, error) { func (tr *Reader) Next() (*Header, error) {
var hdr *Header var hdr *Header
if tr.err == nil { if tr.err == nil {
@ -108,7 +110,13 @@ func (tr *Reader) Next() (*Header, error) {
// We actually read the whole file, // We actually read the whole file,
// but this skips alignment padding // but this skips alignment padding
tr.skipUnread() tr.skipUnread()
if tr.err != nil {
return nil, tr.err
}
hdr = tr.readHeader() hdr = tr.readHeader()
if hdr == nil {
return nil, tr.err
}
mergePAX(hdr, headers) mergePAX(hdr, headers)
// Check for a PAX format sparse file // Check for a PAX format sparse file
@ -331,7 +339,7 @@ func parsePAX(r io.Reader) (map[string]string, error) {
} }
// Parse the first token as a decimal integer. // Parse the first token as a decimal integer.
n, err := strconv.ParseInt(string(buf[:sp]), 10, 0) n, err := strconv.ParseInt(string(buf[:sp]), 10, 0)
if err != nil { if err != nil || n < 5 || int64(len(buf)) < n {
return nil, ErrHeader return nil, ErrHeader
} }
// Extract everything between the decimal and the n -1 on the // Extract everything between the decimal and the n -1 on the
@ -461,6 +469,10 @@ func (tr *Reader) readHeader() *Header {
hdr.Uid = int(tr.octal(s.next(8))) hdr.Uid = int(tr.octal(s.next(8)))
hdr.Gid = int(tr.octal(s.next(8))) hdr.Gid = int(tr.octal(s.next(8)))
hdr.Size = tr.octal(s.next(12)) hdr.Size = tr.octal(s.next(12))
if hdr.Size < 0 {
tr.err = ErrHeader
return nil
}
hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0) hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0)
s.next(8) // chksum s.next(8) // chksum
hdr.Typeflag = s.next(1)[0] hdr.Typeflag = s.next(1)[0]
@ -785,6 +797,9 @@ func (sfr *sparseFileReader) Read(b []byte) (n int, err error) {
// Otherwise, we're at the end of the file // Otherwise, we're at the end of the file
return 0, io.EOF return 0, io.EOF
} }
if sfr.tot < sfr.sp[0].offset {
return 0, io.ErrUnexpectedEOF
}
if sfr.pos < sfr.sp[0].offset { if sfr.pos < sfr.sp[0].offset {
// We're in a hole // We're in a hole
n = sfr.readHole(b, sfr.sp[0].offset) n = sfr.readHole(b, sfr.sp[0].offset)

View File

@ -462,11 +462,16 @@ func TestParsePAXHeader(t *testing.T) {
t.Error("Buffer wasn't consumed") t.Error("Buffer wasn't consumed")
} }
} }
badHeader := bytes.NewReader([]byte("3 somelongkey=")) badHeaderTests := [][]byte{
if _, err := parsePAX(badHeader); err != ErrHeader { []byte("3 somelongkey=\n"),
[]byte("50 tooshort=\n"),
}
for _, test := range badHeaderTests {
if _, err := parsePAX(bytes.NewReader(test)); err != ErrHeader {
t.Fatal("Unexpected success when parsing bad header") t.Fatal("Unexpected success when parsing bad header")
} }
} }
}
func TestParsePAXTime(t *testing.T) { func TestParsePAXTime(t *testing.T) {
// Some valid PAX time values // Some valid PAX time values
@ -741,3 +746,53 @@ func TestUninitializedRead(t *testing.T) {
} }
} }
// Negative header size should not cause panic.
// Issues 10959 and 10960.
func TestNegativeHdrSize(t *testing.T) {
f, err := os.Open("testdata/neg-size.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err != ErrHeader {
t.Error("want ErrHeader, got", err)
}
io.Copy(ioutil.Discard, r)
}
// This used to hang in (*sparseFileReader).readHole due to missing
// verification of sparse offsets against file size.
func TestIssue10968(t *testing.T) {
f, err := os.Open("testdata/issue10968.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(ioutil.Discard, r)
if err != io.ErrUnexpectedEOF {
t.Fatalf("expected %q, got %q", io.ErrUnexpectedEOF, err)
}
}
// Do not panic if there are errors in header blocks after the pax header.
// Issue 11169
func TestIssue11169(t *testing.T) {
f, err := os.Open("testdata/issue11169.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err == nil {
t.Fatal("Unexpected success")
}
}

View File

@ -147,17 +147,6 @@ func TestHeaderRoundTrip(t *testing.T) {
}, },
fm: 0644, fm: 0644,
}, },
// hard link.
{
h: &Header{
Name: "hard.txt",
Mode: 0644 | c_ISLNK,
Size: 0,
ModTime: time.Unix(1360600916, 0),
Typeflag: TypeLink,
},
fm: 0644 | os.ModeSymlink,
},
// symbolic link. // symbolic link.
{ {
h: &Header{ h: &Header{
@ -246,6 +235,33 @@ func TestHeaderRoundTrip(t *testing.T) {
}, },
fm: 0600 | os.ModeSticky, fm: 0600 | os.ModeSticky,
}, },
// hard link.
{
h: &Header{
Name: "hard.txt",
Mode: 0644 | c_ISREG,
Size: 0,
Linkname: "file.txt",
ModTime: time.Unix(1360600916, 0),
Typeflag: TypeLink,
},
fm: 0644,
},
// More information.
{
h: &Header{
Name: "info.txt",
Mode: 0600 | c_ISREG,
Size: 0,
Uid: 1000,
Gid: 1000,
ModTime: time.Unix(1360602540, 0),
Uname: "slartibartfast",
Gname: "users",
Typeflag: TypeReg,
},
fm: 0600,
},
} }
for i, g := range golden { for i, g := range golden {
@ -268,12 +284,37 @@ func TestHeaderRoundTrip(t *testing.T) {
if got, want := h2.Size, g.h.Size; got != want { if got, want := h2.Size, g.h.Size; got != want {
t.Errorf("i=%d: Size: got %v, want %v", i, got, want) t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
} }
if got, want := h2.Uid, g.h.Uid; got != want {
t.Errorf("i=%d: Uid: got %d, want %d", i, got, want)
}
if got, want := h2.Gid, g.h.Gid; got != want {
t.Errorf("i=%d: Gid: got %d, want %d", i, got, want)
}
if got, want := h2.Uname, g.h.Uname; got != want {
t.Errorf("i=%d: Uname: got %q, want %q", i, got, want)
}
if got, want := h2.Gname, g.h.Gname; got != want {
t.Errorf("i=%d: Gname: got %q, want %q", i, got, want)
}
if got, want := h2.Linkname, g.h.Linkname; got != want {
t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want)
}
if got, want := h2.Typeflag, g.h.Typeflag; got != want {
t.Logf("%#v %#v", g.h, fi.Sys())
t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want)
}
if got, want := h2.Mode, g.h.Mode; got != want { if got, want := h2.Mode, g.h.Mode; got != want {
t.Errorf("i=%d: Mode: got %o, want %o", i, got, want) t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
} }
if got, want := fi.Mode(), g.fm; got != want { if got, want := fi.Mode(), g.fm; got != want {
t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want) t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
} }
if got, want := h2.AccessTime, g.h.AccessTime; got != want {
t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want)
}
if got, want := h2.ChangeTime, g.h.ChangeTime; got != want {
t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want)
}
if got, want := h2.ModTime, g.h.ModTime; got != want { if got, want := h2.ModTime, g.h.ModTime; got != want {
t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want) t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -355,7 +355,7 @@ func paxHeader(msg string) string {
// hdr.Size bytes are written after WriteHeader. // hdr.Size bytes are written after WriteHeader.
func (tw *Writer) Write(b []byte) (n int, err error) { func (tw *Writer) Write(b []byte) (n int, err error) {
if tw.closed { if tw.closed {
err = ErrWriteTooLong err = ErrWriteAfterClose
return return
} }
overwrite := false overwrite := false

View File

@ -147,6 +147,44 @@ var writerTests = []*writerTest{
}, },
}, },
}, },
// This file was produced using gnu tar 1.26
// echo "Slartibartfast" > file.txt
// ln file.txt hard.txt
// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
{
file: "testdata/hardlink.tar",
entries: []*writerTestEntry{
{
header: &Header{
Name: "file.txt",
Mode: 0644,
Uid: 1000,
Gid: 100,
Size: 15,
ModTime: time.Unix(1425484303, 0),
Typeflag: '0',
Uname: "vbatts",
Gname: "users",
},
contents: "Slartibartfast\n",
},
{
header: &Header{
Name: "hard.txt",
Mode: 0644,
Uid: 1000,
Gid: 100,
Size: 0,
ModTime: time.Unix(1425484303, 0),
Typeflag: '1',
Linkname: "file.txt",
Uname: "vbatts",
Gname: "users",
},
// no contents
},
},
},
} }
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection. // Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
@ -489,3 +527,20 @@ func TestValidTypeflagWithPAXHeader(t *testing.T) {
} }
} }
} }
func TestWriteAfterClose(t *testing.T) {
var buffer bytes.Buffer
tw := NewWriter(&buffer)
hdr := &Header{
Name: "small.txt",
Size: 5,
}
if err := tw.WriteHeader(hdr); err != nil {
t.Fatalf("Failed to write header: %s", err)
}
tw.Close()
if _, err := tw.Write([]byte("Kilts")); err != ErrWriteAfterClose {
t.Fatalf("Write: got %v; want ErrWriteAfterClose", err)
}
}

View File

@ -8,6 +8,7 @@ import (
"bufio" "bufio"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"hash" "hash"
"hash/crc32" "hash/crc32"
"io" "io"
@ -77,6 +78,9 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
if err != nil { if err != nil {
return err return err
} }
if end.directoryRecords > uint64(size)/fileHeaderLen {
return fmt.Errorf("archive/zip: TOC declares impossible %d files in %d byte zip", end.directoryRecords, size)
}
z.r = r z.r = r
z.File = make([]*File, 0, end.directoryRecords) z.File = make([]*File, 0, end.directoryRecords)
z.Comment = end.comment z.Comment = end.comment
@ -146,13 +150,19 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
if f.hasDataDescriptor() { if f.hasDataDescriptor() {
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen) desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
} }
rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil} rc = &checksumReader{
rc: rc,
hash: crc32.NewIEEE(),
f: f,
desr: desr,
}
return return
} }
type checksumReader struct { type checksumReader struct {
rc io.ReadCloser rc io.ReadCloser
hash hash.Hash32 hash hash.Hash32
nread uint64 // number of bytes read so far
f *File f *File
desr io.Reader // if non-nil, where to read the data descriptor desr io.Reader // if non-nil, where to read the data descriptor
err error // sticky error err error // sticky error
@ -164,13 +174,21 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
} }
n, err = r.rc.Read(b) n, err = r.rc.Read(b)
r.hash.Write(b[:n]) r.hash.Write(b[:n])
r.nread += uint64(n)
if err == nil { if err == nil {
return return
} }
if err == io.EOF { if err == io.EOF {
if r.nread != r.f.UncompressedSize64 {
return 0, io.ErrUnexpectedEOF
}
if r.desr != nil { if r.desr != nil {
if err1 := readDataDescriptor(r.desr, r.f); err1 != nil { if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
if err1 == io.EOF {
err = io.ErrUnexpectedEOF
} else {
err = err1 err = err1
}
} else if r.hash.Sum32() != r.f.CRC32 { } else if r.hash.Sum32() != r.f.CRC32 {
err = ErrChecksum err = ErrChecksum
} }

View File

@ -531,3 +531,77 @@ func TestIssue8186(t *testing.T) {
} }
} }
} }
// Verify we return ErrUnexpectedEOF when length is short.
func TestIssue10957(t *testing.T) {
data := []byte("PK\x03\x040000000PK\x01\x0200000" +
"0000000000000000000\x00" +
"\x00\x00\x00\x00\x00000000000000PK\x01" +
"\x020000000000000000000" +
"00000\v\x00\x00\x00\x00\x00000000000" +
"00000000000000PK\x01\x0200" +
"00000000000000000000" +
"00\v\x00\x00\x00\x00\x00000000000000" +
"00000000000PK\x01\x020000<" +
"0\x00\x0000000000000000\v\x00\v" +
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
"00000000PK\x01\x0200000000" +
"0000000000000000\v\x00\x00\x00" +
"\x00\x0000PK\x05\x06000000\x05\x000000" +
"\v\x00\x00\x00\x00\x00")
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
t.Fatal(err)
}
for i, f := range z.File {
r, err := f.Open()
if err != nil {
continue
}
if f.UncompressedSize64 < 1e6 {
n, err := io.Copy(ioutil.Discard, r)
if i == 3 && err != io.ErrUnexpectedEOF {
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
}
if err == nil && uint64(n) != f.UncompressedSize64 {
t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64)
}
}
r.Close()
}
}
// Verify the number of files is sane.
func TestIssue10956(t *testing.T) {
data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" +
"0000PK\x05\x06000000000000" +
"0000\v\x00000\x00\x00\x00\x00\x00\x00\x000")
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
const want = "TOC declares impossible 3472328296227680304 files in 57 byte"
if err == nil && !strings.Contains(err.Error(), want) {
t.Errorf("error = %v; want %q", err, want)
}
}
// Verify we return ErrUnexpectedEOF when reading truncated data descriptor.
func TestIssue11146(t *testing.T) {
data := []byte("PK\x03\x040000000000000000" +
"000000\x01\x00\x00\x000\x01\x00\x00\xff\xff0000" +
"0000000000000000PK\x01\x02" +
"0000\b0\b\x00000000000000" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" +
"\x00\x0000\x01\x0000008\x00\x00\x00\x00\x00")
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
t.Fatal(err)
}
r, err := z.File[0].Open()
if err != nil {
t.Fatal(err)
}
_, err = ioutil.ReadAll(r)
if err != io.ErrUnexpectedEOF {
t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
}
r.Close()
}

View File

@ -81,8 +81,8 @@ type FileHeader struct {
ModifiedTime uint16 // MS-DOS time ModifiedTime uint16 // MS-DOS time
ModifiedDate uint16 // MS-DOS date ModifiedDate uint16 // MS-DOS date
CRC32 uint32 CRC32 uint32
CompressedSize uint32 // deprecated; use CompressedSize64 CompressedSize uint32 // Deprecated: Use CompressedSize64 instead.
UncompressedSize uint32 // deprecated; use UncompressedSize64 UncompressedSize uint32 // Deprecated: Use UncompressedSize64 instead.
CompressedSize64 uint64 CompressedSize64 uint64
UncompressedSize64 uint64 UncompressedSize64 uint64
Extra []byte Extra []byte
@ -233,7 +233,7 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
} }
} }
// isZip64 returns true if the file size exceeds the 32 bit limit // isZip64 reports whether the file size exceeds the 32 bit limit
func (fh *FileHeader) isZip64() bool { func (fh *FileHeader) isZip64() bool {
return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
} }

View File

@ -34,6 +34,17 @@ func NewWriter(w io.Writer) *Writer {
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}} return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
} }
// SetOffset sets the offset of the beginning of the zip data within the
// underlying writer. It should be used when the zip data is appended to an
// existing file, such as a binary executable.
// It must be called before any data is written.
func (w *Writer) SetOffset(n int64) {
if w.cw.count != 0 {
panic("zip: SetOffset called after data was written")
}
w.cw.count = n
}
// Flush flushes any buffered data to the underlying writer. // Flush flushes any buffered data to the underlying writer.
// Calling Flush is not normally necessary; calling Close is sufficient. // Calling Flush is not normally necessary; calling Close is sufficient.
func (w *Writer) Flush() error { func (w *Writer) Flush() error {
@ -122,7 +133,7 @@ func (w *Writer) Close() error {
// zip64 end of central directory record // zip64 end of central directory record
b.uint32(directory64EndSignature) b.uint32(directory64EndSignature)
b.uint64(directory64EndLen) b.uint64(directory64EndLen - 12) // length minus signature (uint32) and length fields (uint64)
b.uint16(zipVersion45) // version made by b.uint16(zipVersion45) // version made by
b.uint16(zipVersion45) // version needed to extract b.uint16(zipVersion45) // version needed to extract
b.uint32(0) // number of this disk b.uint32(0) // number of this disk
@ -184,14 +195,20 @@ func (w *Writer) Create(name string) (io.Writer, error) {
// CreateHeader adds a file to the zip file using the provided FileHeader // CreateHeader adds a file to the zip file using the provided FileHeader
// for the file metadata. // for the file metadata.
// It returns a Writer to which the file contents should be written. // It returns a Writer to which the file contents should be written.
//
// The file's contents must be written to the io.Writer before the next // The file's contents must be written to the io.Writer before the next
// call to Create, CreateHeader, or Close. // call to Create, CreateHeader, or Close. The provided FileHeader fh
// must not be modified after a call to CreateHeader.
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
if w.last != nil && !w.last.closed { if w.last != nil && !w.last.closed {
if err := w.last.close(); err != nil { if err := w.last.close(); err != nil {
return nil, err return nil, err
} }
} }
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
// See https://golang.org/issue/11144 confusion.
return nil, errors.New("archive/zip: invalid duplicate FileHeader")
}
fh.Flags |= 0x8 // we will write a data descriptor fh.Flags |= 0x8 // we will write a data descriptor

View File

@ -87,6 +87,41 @@ func TestWriter(t *testing.T) {
} }
} }
func TestWriterOffset(t *testing.T) {
largeData := make([]byte, 1<<17)
for i := range largeData {
largeData[i] = byte(rand.Int())
}
writeTests[1].Data = largeData
defer func() {
writeTests[1].Data = nil
}()
// write a zip file
buf := new(bytes.Buffer)
existingData := []byte{1, 2, 3, 1, 2, 3, 1, 2, 3}
n, _ := buf.Write(existingData)
w := NewWriter(buf)
w.SetOffset(int64(n))
for _, wt := range writeTests {
testCreate(t, w, &wt)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// read it back
r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
if err != nil {
t.Fatal(err)
}
for i, wt := range writeTests {
testReadFile(t, r.File[i], &wt)
}
}
func TestWriterFlush(t *testing.T) { func TestWriterFlush(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
w := NewWriter(struct{ io.Writer }{&buf}) w := NewWriter(struct{ io.Writer }{&buf})

View File

@ -229,10 +229,11 @@ func TestZip64(t *testing.T) {
t.Skip("slow test; skipping") t.Skip("slow test; skipping")
} }
const size = 1 << 32 // before the "END\n" part const size = 1 << 32 // before the "END\n" part
testZip64(t, size) buf := testZip64(t, size)
testZip64DirectoryRecordLength(buf, t)
} }
func testZip64(t testing.TB, size int64) { func testZip64(t testing.TB, size int64) *rleBuffer {
const chunkSize = 1024 const chunkSize = 1024
chunks := int(size / chunkSize) chunks := int(size / chunkSize)
// write 2^32 bytes plus "END\n" to a zip file // write 2^32 bytes plus "END\n" to a zip file
@ -302,6 +303,37 @@ func testZip64(t testing.TB, size int64) {
if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want { if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want {
t.Errorf("UncompressedSize64 %d, want %d", got, want) t.Errorf("UncompressedSize64 %d, want %d", got, want)
} }
return buf
}
// Issue 9857
func testZip64DirectoryRecordLength(buf *rleBuffer, t *testing.T) {
d := make([]byte, 1024)
if _, err := buf.ReadAt(d, buf.Size()-int64(len(d))); err != nil {
t.Fatal("read:", err)
}
sigOff := findSignatureInBlock(d)
dirOff, err := findDirectory64End(buf, buf.Size()-int64(len(d))+int64(sigOff))
if err != nil {
t.Fatal("findDirectory64End:", err)
}
d = make([]byte, directory64EndLen)
if _, err := buf.ReadAt(d, dirOff); err != nil {
t.Fatal("read:", err)
}
b := readBuf(d)
if sig := b.uint32(); sig != directory64EndSignature {
t.Fatalf("Expected directory64EndSignature (%d), got %d", directory64EndSignature, sig)
}
size := b.uint64()
if size != directory64EndLen-12 {
t.Fatalf("Expected length of %d, got %d", directory64EndLen-12, size)
}
} }
func testInvalidHeader(h *FileHeader, t *testing.T) { func testInvalidHeader(h *FileHeader, t *testing.T) {

View File

@ -144,6 +144,39 @@ func (b *Reader) Peek(n int) ([]byte, error) {
return b.buf[b.r : b.r+n], err return b.buf[b.r : b.r+n], err
} }
// Discard skips the next n bytes, returning the number of bytes discarded.
//
// If Discard skips fewer than n bytes, it also returns an error.
// If 0 <= n <= b.Buffered(), Discard is guaranteed to succeed without
// reading from the underlying io.Reader.
func (b *Reader) Discard(n int) (discarded int, err error) {
if n < 0 {
return 0, ErrNegativeCount
}
if n == 0 {
return
}
remain := n
for {
skip := b.Buffered()
if skip == 0 {
b.fill()
skip = b.Buffered()
}
if skip > remain {
skip = remain
}
b.r += skip
remain -= skip
if remain == 0 {
return n, nil
}
if b.err != nil {
return n - remain, b.readErr()
}
}
}
// Read reads data into p. // Read reads data into p.
// It returns the number of bytes read into p. // It returns the number of bytes read into p.
// It calls Read at most once on the underlying Reader, // It calls Read at most once on the underlying Reader,
@ -367,7 +400,6 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
// accumulating full buffers. // accumulating full buffers.
var frag []byte var frag []byte
var full [][]byte var full [][]byte
err = nil
for { for {
var e error var e error

View File

@ -1268,6 +1268,135 @@ func TestWriterReset(t *testing.T) {
} }
} }
func TestReaderDiscard(t *testing.T) {
tests := []struct {
name string
r io.Reader
bufSize int // 0 means 16
peekSize int
n int // input to Discard
want int // from Discard
wantErr error // from Discard
wantBuffered int
}{
{
name: "normal case",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
peekSize: 16,
n: 6,
want: 6,
wantBuffered: 10,
},
{
name: "discard causing read",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 6,
want: 6,
wantBuffered: 10,
},
{
name: "discard all without peek",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 26,
want: 26,
wantBuffered: 0,
},
{
name: "discard more than end",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 27,
want: 26,
wantErr: io.EOF,
wantBuffered: 0,
},
// Any error from filling shouldn't show up until we
// get past the valid bytes. Here we return we return 5 valid bytes at the same time
// as an error, but test that we don't see the error from Discard.
{
name: "fill error, discard less",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 4,
want: 4,
wantErr: nil,
wantBuffered: 1,
},
{
name: "fill error, discard equal",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 5,
want: 5,
wantErr: nil,
wantBuffered: 0,
},
{
name: "fill error, discard more",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 6,
want: 5,
wantErr: errors.New("5-then-error"),
wantBuffered: 0,
},
// Discard of 0 shouldn't cause a read:
{
name: "discard zero",
r: newScriptedReader(), // will panic on Read
n: 0,
want: 0,
wantErr: nil,
wantBuffered: 0,
},
{
name: "discard negative",
r: newScriptedReader(), // will panic on Read
n: -1,
want: 0,
wantErr: ErrNegativeCount,
wantBuffered: 0,
},
}
for _, tt := range tests {
br := NewReaderSize(tt.r, tt.bufSize)
if tt.peekSize > 0 {
peekBuf, err := br.Peek(tt.peekSize)
if err != nil {
t.Errorf("%s: Peek(%d): %v", tt.name, tt.peekSize, err)
continue
}
if len(peekBuf) != tt.peekSize {
t.Errorf("%s: len(Peek(%d)) = %v; want %v", tt.name, tt.peekSize, len(peekBuf), tt.peekSize)
continue
}
}
discarded, err := br.Discard(tt.n)
if ge, we := fmt.Sprint(err), fmt.Sprint(tt.wantErr); discarded != tt.want || ge != we {
t.Errorf("%s: Discard(%d) = (%v, %v); want (%v, %v)", tt.name, tt.n, discarded, ge, tt.want, we)
continue
}
if bn := br.Buffered(); bn != tt.wantBuffered {
t.Errorf("%s: after Discard, Buffered = %d; want %d", tt.name, bn, tt.wantBuffered)
}
}
}
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have. // An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct { type onlyReader struct {
io.Reader io.Reader
@ -1278,6 +1407,23 @@ type onlyWriter struct {
io.Writer io.Writer
} }
// A scriptedReader is an io.Reader that executes its steps sequentially.
type scriptedReader []func(p []byte) (n int, err error)
func (sr *scriptedReader) Read(p []byte) (n int, err error) {
if len(*sr) == 0 {
panic("too many Read calls on scripted Reader. No steps remain.")
}
step := (*sr)[0]
*sr = (*sr)[1:]
return step(p)
}
func newScriptedReader(steps ...func(p []byte) (n int, err error)) io.Reader {
sr := scriptedReader(steps)
return &sr
}
func BenchmarkReaderCopyOptimal(b *testing.B) { func BenchmarkReaderCopyOptimal(b *testing.B) {
// Optimal case is where the underlying reader implements io.WriterTo // Optimal case is where the underlying reader implements io.WriterTo
srcBuf := bytes.NewBuffer(make([]byte, 8192)) srcBuf := bytes.NewBuffer(make([]byte, 8192))

View File

@ -109,7 +109,7 @@ func (s *Scanner) Text() string {
// After Scan returns false, the Err method will return any error that // After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err // occurred during scanning, except that if it was io.EOF, Err
// will return nil. // will return nil.
// Split panics if the split function returns 100 empty tokens without // Scan panics if the split function returns 100 empty tokens without
// advancing the input. This is a common error mode for scanners. // advancing the input. This is a common error mode for scanners.
func (s *Scanner) Scan() bool { func (s *Scanner) Scan() bool {
// Loop until we have a token. // Loop until we have a token.

View File

@ -236,14 +236,14 @@ func panic(v interface{})
// panicking. // panicking.
func recover() interface{} func recover() interface{}
// The print built-in function formats its arguments in an implementation- // The print built-in function formats its arguments in an
// specific way and writes the result to standard error. // implementation-specific way and writes the result to standard error.
// Print is useful for bootstrapping and debugging; it is not guaranteed // Print is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language. // to stay in the language.
func print(args ...Type) func print(args ...Type)
// The println built-in function formats its arguments in an implementation- // The println built-in function formats its arguments in an
// specific way and writes the result to standard error. // implementation-specific way and writes the result to standard error.
// Spaces are always added between arguments and a newline is appended. // Spaces are always added between arguments and a newline is appended.
// Println is useful for bootstrapping and debugging; it is not guaranteed // Println is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language. // to stay in the language.

View File

@ -56,6 +56,10 @@ func (b *Buffer) String() string {
// b.Len() == len(b.Bytes()). // b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int { return len(b.buf) - b.off } func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Cap returns the capacity of the buffer's underlying byte slice, that is, the
// total space allocated for the buffer's data.
func (b *Buffer) Cap() int { return cap(b.buf) }
// Truncate discards all but the first n unread bytes from the buffer. // Truncate discards all but the first n unread bytes from the buffer.
// It panics if n is negative or greater than the length of the buffer. // It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) { func (b *Buffer) Truncate(n int) {

View File

@ -231,6 +231,23 @@ func TestMixedReadsAndWrites(t *testing.T) {
empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len()))
} }
func TestCapWithPreallocatedSlice(t *testing.T) {
buf := NewBuffer(make([]byte, 10))
n := buf.Cap()
if n != 10 {
t.Errorf("expected 10, got %d", n)
}
}
func TestCapWithSliceAndWrittenData(t *testing.T) {
buf := NewBuffer(make([]byte, 0, 10))
buf.Write([]byte("test"))
n := buf.Cap()
if n != 10 {
t.Errorf("expected 10, got %d", n)
}
}
func TestNil(t *testing.T) { func TestNil(t *testing.T) {
var b *Buffer var b *Buffer
if b.String() != "<nil>" { if b.String() != "<nil>" {

View File

@ -23,7 +23,7 @@ func equalPortable(a, b []byte) bool {
return true return true
} }
// explode splits s into a slice of UTF-8 sequences, one per Unicode character (still slices of bytes), // explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes. // up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
func explode(s []byte, n int) [][]byte { func explode(s []byte, n int) [][]byte {
if n <= 0 { if n <= 0 {
@ -47,6 +47,7 @@ func explode(s []byte, n int) [][]byte {
} }
// Count counts the number of non-overlapping instances of sep in s. // Count counts the number of non-overlapping instances of sep in s.
// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
func Count(s, sep []byte) int { func Count(s, sep []byte) int {
n := len(sep) n := len(sep)
if n == 0 { if n == 0 {
@ -137,6 +138,16 @@ func LastIndex(s, sep []byte) int {
return -1 return -1
} }
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
func LastIndexByte(s []byte, c byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == c {
return i
}
}
return -1
}
// IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points. // IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
// It returns the byte index of the first occurrence in s of the given rune. // It returns the byte index of the first occurrence in s of the given rune.
// It returns -1 if rune is not present in s. // It returns -1 if rune is not present in s.
@ -442,7 +453,7 @@ func isSeparator(r rune) bool {
// Title returns a copy of s with all Unicode letters that begin words // Title returns a copy of s with all Unicode letters that begin words
// mapped to their title case. // mapped to their title case.
// //
// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly. // BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
func Title(s []byte) []byte { func Title(s []byte) []byte {
// Use a closure here to remember state. // Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling // Hackish but effective. Depends on Map scanning in order and calling

View File

@ -21,4 +21,4 @@ func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s
// Compare returns an integer comparing two byte slices lexicographically. // Compare returns an integer comparing two byte slices lexicographically.
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. // The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
// A nil argument is equivalent to an empty slice. // A nil argument is equivalent to an empty slice.
func Compare(a, b []byte) int // ../runtime/noasm_arm.goc or ../runtime/asm_{386,amd64}.s func Compare(a, b []byte) int // ../runtime/noasm.go or ../runtime/asm_{386,amd64}.s

View File

@ -265,6 +265,23 @@ func TestIndexByte(t *testing.T) {
} }
} }
func TestLastIndexByte(t *testing.T) {
testCases := []BinOpTest{
{"", "q", -1},
{"abcdef", "q", -1},
{"abcdefabcdef", "a", len("abcdef")}, // something in the middle
{"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
{"zabcdefabcdef", "z", 0}, // first byte
{"a☺b☻c☹d", "b", len("a☺")}, // non-ascii
}
for _, test := range testCases {
actual := LastIndexByte([]byte(test.a), test.b[0])
if actual != test.i {
t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i)
}
}
}
// test a larger buffer with different sizes and alignments // test a larger buffer with different sizes and alignments
func TestIndexByteBig(t *testing.T) { func TestIndexByteBig(t *testing.T) {
var n = 1024 var n = 1024

View File

@ -17,6 +17,8 @@ var compareTests = []struct {
{[]byte("a"), []byte(""), 1}, {[]byte("a"), []byte(""), 1},
{[]byte(""), []byte("a"), -1}, {[]byte(""), []byte("a"), -1},
{[]byte("abc"), []byte("abc"), 0}, {[]byte("abc"), []byte("abc"), 0},
{[]byte("abd"), []byte("abc"), 1},
{[]byte("abc"), []byte("abd"), -1},
{[]byte("ab"), []byte("abc"), -1}, {[]byte("ab"), []byte("abc"), -1},
{[]byte("abc"), []byte("ab"), 1}, {[]byte("abc"), []byte("ab"), 1},
{[]byte("x"), []byte("ab"), 1}, {[]byte("x"), []byte("ab"), 1},
@ -27,6 +29,7 @@ var compareTests = []struct {
{[]byte("abcdefgh"), []byte("abcdefgh"), 0}, {[]byte("abcdefgh"), []byte("abcdefgh"), 0},
{[]byte("abcdefghi"), []byte("abcdefghi"), 0}, {[]byte("abcdefghi"), []byte("abcdefghi"), 0},
{[]byte("abcdefghi"), []byte("abcdefghj"), -1}, {[]byte("abcdefghi"), []byte("abcdefghj"), -1},
{[]byte("abcdefghj"), []byte("abcdefghi"), 1},
// nil tests // nil tests
{nil, nil, 0}, {nil, nil, 0},
{[]byte(""), nil, 0}, {[]byte(""), nil, 0},

View File

@ -7,7 +7,3 @@ package bytes
// Export func for testing // Export func for testing
var IndexBytePortable = indexBytePortable var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable var EqualPortable = equalPortable
func (b *Buffer) Cap() int {
return cap(b.buf)
}

View File

@ -29,6 +29,12 @@ func (r *Reader) Len() int {
return int(int64(len(r.s)) - r.i) return int(int64(len(r.s)) - r.i)
} }
// Size returns the original length of the underlying byte slice.
// Size is the number of bytes available for reading via ReadAt.
// The returned value is always the same and is not affected by calls
// to any other method.
func (r *Reader) Size() int64 { return int64(len(r.s)) }
func (r *Reader) Read(b []byte) (n int, err error) { func (r *Reader) Read(b []byte) (n int, err error) {
if len(b) == 0 { if len(b) == 0 {
return 0, nil return 0, nil

View File

@ -244,3 +244,15 @@ func TestReaderCopyNothing(t *testing.T) {
t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut) t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
} }
} }
// tests that Len is affected by reads, but Size is not.
func TestReaderLenSize(t *testing.T) {
r := NewReader([]byte("abc"))
io.CopyN(ioutil.Discard, r, 1)
if r.Len() != 2 {
t.Errorf("Len = %d; want 2", r.Len())
}
if r.Size() != 3 {
t.Errorf("Size = %d; want 3", r.Size())
}
}

View File

@ -235,9 +235,17 @@ func (f *File) saveExport(x interface{}, context string) {
error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name) error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
} }
doc := ""
for _, c1 := range n.Doc.List {
if c1 != c {
doc += c1.Text + "\n"
}
}
f.ExpFunc = append(f.ExpFunc, &ExpFunc{ f.ExpFunc = append(f.ExpFunc, &ExpFunc{
Func: n, Func: n,
ExpName: name, ExpName: name,
Doc: doc,
}) })
break break
} }

View File

@ -20,16 +20,23 @@ the C parts of the package. For example:
// #include <errno.h> // #include <errno.h>
import "C" import "C"
The preamble may contain any C code, including function and variable
declarations and definitions. These may then be referred to from Go
code as though they were defined in the package "C". All names
declared in the preamble may be used, even if they start with a
lower-case letter. Exception: static variables in the preamble may
not be referenced from Go code; static functions are permitted.
See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
"C? Go? Cgo!" for an introduction to using cgo: "C? Go? Cgo!" for an introduction to using cgo:
http://golang.org/doc/articles/c_go_cgo.html. https://golang.org/doc/articles/c_go_cgo.html.
CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
directives within these comments to tweak the behavior of the C or C++ directives within these comments to tweak the behavior of the C or C++
compiler. Values defined in multiple directives are concatenated compiler. Values defined in multiple directives are concatenated
together. The directive can include a list of build constraints limiting its together. The directive can include a list of build constraints limiting its
effect to systems satisfying one of the constraints effect to systems satisfying one of the constraints
(see http://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax). (see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
For example: For example:
// #cgo CFLAGS: -DPNG_DEBUG=1 // #cgo CFLAGS: -DPNG_DEBUG=1
@ -60,6 +67,18 @@ concatenated and used at link time. All the pkg-config directives are
concatenated and sent to pkg-config simultaneously to add to each appropriate concatenated and sent to pkg-config simultaneously to add to each appropriate
set of command-line flags. set of command-line flags.
When the cgo directives are parsed, any occurrence of the string ${SRCDIR}
will be replaced by the absolute path to the directory containing the source
file. This allows pre-compiled static libraries to be included in the package
directory and linked properly.
For example if package foo is in the directory /go/src/foo:
// #cgo LDFLAGS: -L${SRCDIR}/libs -lfoo
Will be expanded to:
// #cgo LDFLAGS: -L/go/src/foo/libs -lfoo
When the Go tool sees that one or more Go files use the special import When the Go tool sees that one or more Go files use the special import
"C", it will look for other non-Go files in the directory and compile "C", it will look for other non-Go files in the directory and compile
them as part of the Go package. Any .c, .s, or .S files will be them as part of the Go package. Any .c, .s, or .S files will be
@ -71,17 +90,19 @@ compilers may be changed by the CC and CXX environment variables,
respectively; those environment variables may include command line respectively; those environment variables may include command line
options. options.
To enable cgo during cross compiling builds, set the CGO_ENABLED The cgo tool is enabled by default for native builds on systems where
environment variable to 1 when building the Go tools with make.bash. it is expected to work. It is disabled by default when
Also, set CC_FOR_TARGET to the C cross compiler for the target. CC will cross-compiling. You can control this by setting the CGO_ENABLED
be used for compiling for the host. environment variable when running the go tool: set it to 1 to enable
the use of cgo, and to 0 to disable it. The go tool will set the
build constraint "cgo" if cgo is enabled.
After the Go tools are built, when running the go command, CC_FOR_TARGET is When cross-compiling, you must specify a C cross-compiler for cgo to
ignored. The value of CC_FOR_TARGET when running make.bash is the default use. You can do this by setting the CC_FOR_TARGET environment
compiler. However, you can set the environment variable CC, not CC_FOR_TARGET, variable when building the toolchain using make.bash, or by setting
to control the compiler when running the go tool. the CC environment variable any time you run the go tool. The
CXX_FOR_TARGET and CXX environment variables work in a similar way for
CXX_FOR_TARGET works in a similar way for C++ code. C++ code.
Go references to C Go references to C
@ -195,16 +216,18 @@ Not all Go types can be mapped to C types in a useful way.
Using //export in a file places a restriction on the preamble: Using //export in a file places a restriction on the preamble:
since it is copied into two different C output files, it must not since it is copied into two different C output files, it must not
contain any definitions, only declarations. Definitions must be contain any definitions, only declarations. If a file contains both
placed in preambles in other files, or in C source files. definitions and declarations, then the two output files will produce
duplicate symbols and the linker will fail. To avoid this, definitions
must be placed in preambles in other files, or in C source files.
Using cgo directly Using cgo directly
Usage: Usage:
go tool cgo [cgo options] [-- compiler options] file.go go tool cgo [cgo options] [-- compiler options] gofiles...
Cgo transforms the input file.go into four output files: two Go source Cgo transforms the specified input Go source files into several output
files, a C file for 6c (or 8c or 5c), and a C file for gcc. Go and C source files.
The compiler options are passed through uninterpreted when The compiler options are passed through uninterpreted when
invoking the C compiler to compile the C parts of the package. invoking the C compiler to compile the C parts of the package.
@ -217,18 +240,23 @@ The following options are available when running cgo directly:
build when building a cgo package. build when building a cgo package.
-dynout file -dynout file
Write -dynimport output to file. Write -dynimport output to file.
-dynpackage package
Set Go package for -dynimport output.
-dynlinker -dynlinker
Write dynamic linker as part of -dynimport output. Write dynamic linker as part of -dynimport output.
-godefs -godefs
Write out input file in Go syntax replacing C package Write out input file in Go syntax replacing C package
names with real values. Used to generate files in the names with real values. Used to generate files in the
syscall package when bootstrapping a new target. syscall package when bootstrapping a new target.
-cdefs
Like -godefs, but write file in C syntax.
Used to generate files in the runtime package when
bootstrapping a new target.
-objdir directory -objdir directory
Put all generated files in directory. Put all generated files in directory.
-importpath string
The import path for the Go package. Optional; used for
nicer comments in the generated files.
-exportheader file
If there are any exported functions, write the
generated export declarations to file.
C code can #include this to see the declarations.
-gccgo -gccgo
Generate output for the gccgo compiler rather than the Generate output for the gccgo compiler rather than the
gc compiler. gc compiler.
@ -363,9 +391,9 @@ the translation process.
Translating Go Translating Go
[The rest of this comment refers to 6g and 6c, the Go and C compilers [The rest of this comment refers to 6g, the Go compiler that is part
that are part of the amd64 port of the gc Go toolchain. Everything here of the amd64 port of the gc Go toolchain. Everything here applies to
applies to another architecture's compilers as well.] another architecture's compilers as well.]
Given the input Go files x.go and y.go, cgo generates these source Given the input Go files x.go and y.go, cgo generates these source
files: files:
@ -373,44 +401,41 @@ files:
x.cgo1.go # for 6g x.cgo1.go # for 6g
y.cgo1.go # for 6g y.cgo1.go # for 6g
_cgo_gotypes.go # for 6g _cgo_gotypes.go # for 6g
_cgo_defun.c # for 6c _cgo_import.go # for 6g (if -dynout _cgo_import.go)
x.cgo2.c # for gcc x.cgo2.c # for gcc
y.cgo2.c # for gcc y.cgo2.c # for gcc
_cgo_defun.c # for gcc (if -gccgo)
_cgo_export.c # for gcc _cgo_export.c # for gcc
_cgo_export.h # for gcc
_cgo_main.c # for gcc _cgo_main.c # for gcc
_cgo_flags # for alternative build tools
The file x.cgo1.go is a copy of x.go with the import "C" removed and The file x.cgo1.go is a copy of x.go with the import "C" removed and
references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx. references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
The definitions of those identifiers, written as Go functions, types, The definitions of those identifiers, written as Go functions, types,
or variables, are provided in _cgo_gotypes.go. or variables, are provided in _cgo_gotypes.go.
Here is a _cgo_gotypes.go containing definitions for C.flush (provided Here is a _cgo_gotypes.go containing definitions for needed C types:
in the preamble) and C.puts (from stdio):
type _Ctype_char int8 type _Ctype_char int8
type _Ctype_int int32 type _Ctype_int int32
type _Ctype_void [0]byte type _Ctype_void [0]byte
func _Cfunc_CString(string) *_Ctype_char The _cgo_gotypes.go file also contains the definitions of the
func _Cfunc_flush() _Ctype_void functions. They all have similar bodies that invoke runtime·cgocall
func _Cfunc_puts(*_Ctype_char) _Ctype_int to make a switch from the Go runtime world to the system C (GCC-based)
world.
For functions, cgo only writes an external declaration in the Go
output. The implementation is in a combination of C for 6c (meaning
any gc-toolchain compiler) and C for gcc.
The 6c file contains the definitions of the functions. They all have
similar bodies that invoke runtime·cgocall to make a switch from the
Go runtime world to the system C (GCC-based) world.
For example, here is the definition of _Cfunc_puts: For example, here is the definition of _Cfunc_puts:
void _cgo_be59f0f25121_Cfunc_puts(void*); //go:cgo_import_static _cgo_be59f0f25121_Cfunc_puts
//go:linkname __cgofn__cgo_be59f0f25121_Cfunc_puts _cgo_be59f0f25121_Cfunc_puts
var __cgofn__cgo_be59f0f25121_Cfunc_puts byte
var _cgo_be59f0f25121_Cfunc_puts = unsafe.Pointer(&__cgofn__cgo_be59f0f25121_Cfunc_puts)
void func _Cfunc_puts(p0 *_Ctype_char) (r1 _Ctype_int) {
·_Cfunc_puts(struct{uint8 x[1];}p) _cgo_runtime_cgocall(_cgo_be59f0f25121_Cfunc_puts, uintptr(unsafe.Pointer(&p0)))
{ return
runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p);
} }
The hexadecimal number is a hash of cgo's input, chosen to be The hexadecimal number is a hash of cgo's input, chosen to be
@ -421,6 +446,7 @@ file compiled by gcc, the file x.cgo2.c:
void void
_cgo_be59f0f25121_Cfunc_puts(void *v) _cgo_be59f0f25121_Cfunc_puts(void *v)
{ {
_cgo_wait_runtime_init_done();
struct { struct {
char* p0; char* p0;
int r; int r;
@ -429,7 +455,8 @@ file compiled by gcc, the file x.cgo2.c:
a->r = puts((void*)a->p0); a->r = puts((void*)a->p0);
} }
It extracts the arguments from the pointer to _Cfunc_puts's argument It waits for Go runtime to be initialized (required for shared libraries),
extracts the arguments from the pointer to _Cfunc_puts's argument
frame, invokes the system C function (in this case, puts), stores the frame, invokes the system C function (in this case, puts), stores the
result in the frame, and returns. result in the frame, and returns.
@ -448,6 +475,7 @@ _cgo_main.c:
int main() { return 0; } int main() { return 0; }
void crosscall2(void(*fn)(void*, int), void *a, int c) { } void crosscall2(void(*fn)(void*, int), void *a, int c) { }
void _cgo_wait_runtime_init_done() { }
void _cgo_allocate(void *a, int c) { } void _cgo_allocate(void *a, int c) { }
void _cgo_panic(void *a, int c) { } void _cgo_panic(void *a, int c) { }
@ -456,23 +484,21 @@ code generated for gcc. The build process links this stub, along with
_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets _cgo_export.c and *.cgo2.c, into a dynamic executable and then lets
cgo examine the executable. Cgo records the list of shared library cgo examine the executable. Cgo records the list of shared library
references and resolved names and writes them into a new file references and resolved names and writes them into a new file
_cgo_import.c, which looks like: _cgo_import.go, which looks like:
#pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2" //go:cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6" //go:cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6" //go:cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6" //go:cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6" //go:cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic _ _ "libpthread.so.0" //go:cgo_import_dynamic _ _ "libpthread.so.0"
#pragma cgo_import_dynamic _ _ "libc.so.6" //go:cgo_import_dynamic _ _ "libc.so.6"
In the end, the compiled Go package, which will eventually be In the end, the compiled Go package, which will eventually be
presented to 6l as part of a larger program, contains: presented to 6l as part of a larger program, contains:
_go_.6 # 6g-compiled object for _cgo_gotypes.go *.cgo1.go _go_.6 # 6g-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
_cgo_defun.6 # 6c-compiled object for _cgo_defun.c
_all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c _all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c
_cgo_import.6 # 6c-compiled object for _cgo_import.c
The final program will be a dynamic executable, so that 6l can avoid The final program will be a dynamic executable, so that 6l can avoid
needing to process arbitrary .o files. It only needs to process the .o needing to process arbitrary .o files. It only needs to process the .o
@ -496,20 +522,21 @@ Runtime
When using cgo, Go must not assume that it owns all details of the When using cgo, Go must not assume that it owns all details of the
process. In particular it needs to coordinate with C in the use of process. In particular it needs to coordinate with C in the use of
threads and thread-local storage. The runtime package, in its own threads and thread-local storage. The runtime package declares a few
(6c-compiled) C code, declares a few uninitialized (default bss)
variables: variables:
bool runtime·iscgo; var (
void (*libcgo_thread_start)(void*); iscgo bool
void (*initcgo)(G*); _cgo_init unsafe.Pointer
_cgo_thread_start unsafe.Pointer
)
Any package using cgo imports "runtime/cgo", which provides Any package using cgo imports "runtime/cgo", which provides
initializations for these variables. It sets iscgo to 1, initcgo to a initializations for these variables. It sets iscgo to true, _cgo_init
gcc-compiled function that can be called early during program startup, to a gcc-compiled function that can be called early during program
and libcgo_thread_start to a gcc-compiled function that can be used to startup, and _cgo_thread_start to a gcc-compiled function that can be
create a new thread, in place of the runtime's usual direct system used to create a new thread, in place of the runtime's usual direct
calls. system calls.
Internal and External Linking Internal and External Linking
@ -522,12 +549,12 @@ code can only be used as a dynamic library). On the other hand, when
using internal linking, 6l can generate Go binaries by itself. using internal linking, 6l can generate Go binaries by itself.
In order to allow linking arbitrary object files without requiring In order to allow linking arbitrary object files without requiring
dynamic libraries, cgo will soon support an "external" linking mode dynamic libraries, cgo supports an "external" linking mode too. In
too. In external linking mode, 6l does not process any host object external linking mode, 6l does not process any host object files.
files. Instead, it collects all the Go code and writes a single go.o Instead, it collects all the Go code and writes a single go.o object
object file containing it. Then it invokes the host linker (usually file containing it. Then it invokes the host linker (usually gcc) to
gcc) to combine the go.o object file and any supporting non-Go code combine the go.o object file and any supporting non-Go code into a
into a final executable. External linking avoids the dynamic library final executable. External linking avoids the dynamic library
requirement but introduces a requirement that the host linker be requirement but introduces a requirement that the host linker be
present to create such a binary. present to create such a binary.
@ -555,13 +582,13 @@ to be made when linking the final binary.
Linking Directives Linking Directives
In either linking mode, package-specific directives must be passed In either linking mode, package-specific directives must be passed
through to 6l. These are communicated by writing #pragma directives through to 6l. These are communicated by writing //go: directives in a
in a C source file compiled by 6c. The directives are copied into the .6 object file Go source file compiled by 6g. The directives are copied into the .6
and then processed by the linker. object file and then processed by the linker.
The directives are: The directives are:
#pragma cgo_import_dynamic <local> [<remote> ["<library>"]] //go:cgo_import_dynamic <local> [<remote> ["<library>"]]
In internal linking mode, allow an unresolved reference to In internal linking mode, allow an unresolved reference to
<local>, assuming it will be resolved by a dynamic library <local>, assuming it will be resolved by a dynamic library
@ -572,9 +599,9 @@ The directives are:
In the <remote>, # or @ can be used to introduce a symbol version. In the <remote>, # or @ can be used to introduce a symbol version.
Examples: Examples:
#pragma cgo_import_dynamic puts //go:cgo_import_dynamic puts
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 //go:cgo_import_dynamic puts puts#GLIBC_2.2.5
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6" //go:cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
A side effect of the cgo_import_dynamic directive with a A side effect of the cgo_import_dynamic directive with a
library is to make the final binary depend on that dynamic library is to make the final binary depend on that dynamic
@ -582,12 +609,12 @@ The directives are:
symbols, use _ for local and remote. symbols, use _ for local and remote.
Example: Example:
#pragma cgo_import_dynamic _ _ "libc.so.6" //go:cgo_import_dynamic _ _ "libc.so.6"
For compatibility with current versions of SWIG, For compatibility with current versions of SWIG,
#pragma dynimport is an alias for #pragma cgo_import_dynamic. #pragma dynimport is an alias for //go:cgo_import_dynamic.
#pragma cgo_dynamic_linker "<path>" //go:cgo_dynamic_linker "<path>"
In internal linking mode, use "<path>" as the dynamic linker In internal linking mode, use "<path>" as the dynamic linker
in the final binary. This directive is only needed from one in the final binary. This directive is only needed from one
@ -595,9 +622,9 @@ The directives are:
supplied by runtime/cgo. supplied by runtime/cgo.
Example: Example:
#pragma cgo_dynamic_linker "/lib/ld-linux.so.2" //go:cgo_dynamic_linker "/lib/ld-linux.so.2"
#pragma cgo_export_dynamic <local> <remote> //go:cgo_export_dynamic <local> <remote>
In internal linking mode, put the Go symbol In internal linking mode, put the Go symbol
named <local> into the program's exported symbol table as named <local> into the program's exported symbol table as
@ -606,9 +633,9 @@ The directives are:
to share Go's data. to share Go's data.
For compatibility with current versions of SWIG, For compatibility with current versions of SWIG,
#pragma dynexport is an alias for #pragma cgo_export_dynamic. #pragma dynexport is an alias for //go:cgo_export_dynamic.
#pragma cgo_import_static <local> //go:cgo_import_static <local>
In external linking mode, allow unresolved references to In external linking mode, allow unresolved references to
<local> in the go.o object file prepared for the host linker, <local> in the go.o object file prepared for the host linker,
@ -616,9 +643,9 @@ The directives are:
other object files that will be linked with go.o. other object files that will be linked with go.o.
Example: Example:
#pragma cgo_import_static puts_wrapper //go:cgo_import_static puts_wrapper
#pragma cgo_export_static <local> <remote> //go:cgo_export_static <local> <remote>
In external linking mode, put the Go symbol In external linking mode, put the Go symbol
named <local> into the program's exported symbol table as named <local> into the program's exported symbol table as
@ -626,15 +653,15 @@ The directives are:
mechanism makes it possible for C code to call back into Go or mechanism makes it possible for C code to call back into Go or
to share Go's data. to share Go's data.
#pragma cgo_ldflag "<arg>" //go:cgo_ldflag "<arg>"
In external linking mode, invoke the host linker (usually gcc) In external linking mode, invoke the host linker (usually gcc)
with "<arg>" as a command-line argument following the .o files. with "<arg>" as a command-line argument following the .o files.
Note that the arguments are for "gcc", not "ld". Note that the arguments are for "gcc", not "ld".
Example: Example:
#pragma cgo_ldflag "-lpthread" //go:cgo_ldflag "-lpthread"
#pragma cgo_ldflag "-L/usr/local/sqlite3/lib" //go:cgo_ldflag "-L/usr/local/sqlite3/lib"
A package compiled with cgo will include directives for both A package compiled with cgo will include directives for both
internal and external linking; the linker will select the appropriate internal and external linking; the linker will select the appropriate
@ -647,22 +674,18 @@ The following code will be generated by cgo:
// compiled by 6g // compiled by 6g
//go:cgo_ldflag "-lm"
type _Ctype_double float64 type _Ctype_double float64
func _Cfunc_sin(_Ctype_double) _Ctype_double
// compiled by 6c //go:cgo_import_static _cgo_gcc_Cfunc_sin
//go:linkname __cgo_gcc_Cfunc_sin _cgo_gcc_Cfunc_sin
var __cgo_gcc_Cfunc_sin byte
var _cgo_gcc_Cfunc_sin = unsafe.Pointer(&__cgo_gcc_Cfunc_sin)
#pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6" func _Cfunc_sin(p0 _Ctype_double) (r1 _Ctype_double) {
_cgo_runtime_cgocall(_cgo_gcc_Cfunc_sin, uintptr(unsafe.Pointer(&p0)))
#pragma cgo_import_static _cgo_gcc_Cfunc_sin return
#pragma cgo_ldflag "-lm"
void _cgo_gcc_Cfunc_sin(void*);
void
·_Cfunc_sin(struct{uint8 x[16];}p)
{
runtime·cgocall(_cgo_gcc_Cfunc_sin, &p);
} }
// compiled by gcc, into foo.cgo2.o // compiled by gcc, into foo.cgo2.o
@ -682,8 +705,8 @@ using the internal or external mode. If other packages are compiled in
"external only" mode, then the final link will be an external one. "external only" mode, then the final link will be an external one.
Otherwise the link will be an internal one. Otherwise the link will be an internal one.
The directives in the 6c-compiled file are used according to the kind The linking directives are used according to the kind of final link
of final link used. used.
In internal mode, 6l itself processes all the host object files, in In internal mode, 6l itself processes all the host object files, in
particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and
@ -694,10 +717,10 @@ symbol sin with version GLIBC_2.2.5 from the dynamic library
runtime dynamic linker. runtime dynamic linker.
In external mode, 6l does not process any host object files, in In external mode, 6l does not process any host object files, in
particular foo.cgo2.o. It links together the 6g- and 6c-generated particular foo.cgo2.o. It links together the 6g-generated object
object files, along with any other Go code, into a go.o file. While files, along with any other Go code, into a go.o file. While doing
doing that, 6l will discover that there is no definition for that, 6l will discover that there is no definition for
_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This _cgo_gcc_Cfunc_sin, referred to by the 6g-compiled source file. This
is okay, because 6l also processes the cgo_import_static directive and is okay, because 6l also processes the cgo_import_static directive and
knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
object file, so 6l does not treat the missing symbol as an error when object file, so 6l does not treat the missing symbol as an error when

View File

@ -154,20 +154,6 @@ func splitQuoted(s string) (r []string, err error) {
return args, err return args, err
} }
var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
func safeName(s string) bool {
if s == "" {
return false
}
for i := 0; i < len(s); i++ {
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
return false
}
}
return true
}
// Translate rewrites f.AST, the original Go input, to remove // Translate rewrites f.AST, the original Go input, to remove
// references to the imported package C, replacing them with // references to the imported package C, replacing them with
// references to the equivalent Go types, functions, and variables. // references to the equivalent Go types, functions, and variables.
@ -213,6 +199,10 @@ func (p *Package) loadDefines(f *File) {
val = strings.TrimSpace(line[tabIndex:]) val = strings.TrimSpace(line[tabIndex:])
} }
if key == "__clang__" {
p.GccIsClang = true
}
if n := f.Name[key]; n != nil { if n := f.Name[key]; n != nil {
if *debugDefine { if *debugDefine {
fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val) fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
@ -582,7 +572,7 @@ func (p *Package) mangleName(n *Name) {
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
// Go equivalents, now that we have figured out the meaning of all // Go equivalents, now that we have figured out the meaning of all
// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names // the xxx. In *godefs mode, rewriteRef replaces the names
// with full definitions instead of mangled names. // with full definitions instead of mangled names.
func (p *Package) rewriteRef(f *File) { func (p *Package) rewriteRef(f *File) {
// Keep a list of all the functions, to remove the ones // Keep a list of all the functions, to remove the ones
@ -673,6 +663,13 @@ func (p *Package) rewriteRef(f *File) {
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr} expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
} }
case "selector":
if r.Name.Kind == "var" {
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
} else {
error_(r.Pos(), "only C variables allowed in selector expression", fixGo(r.Name.Go))
}
case "type": case "type":
if r.Name.Kind != "type" { if r.Name.Kind != "type" {
error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go)) error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
@ -688,7 +685,7 @@ func (p *Package) rewriteRef(f *File) {
error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go)) error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
} }
} }
if *godefs || *cdefs { if *godefs {
// Substitute definition for mangled type name. // Substitute definition for mangled type name.
if id, ok := expr.(*ast.Ident); ok { if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil { if t := typedef[id.Name]; t != nil {
@ -746,6 +743,10 @@ func (p *Package) gccMachine() []string {
return []string{"-m32"} return []string{"-m32"}
case "arm": case "arm":
return []string{"-marm"} // not thumb return []string{"-marm"} // not thumb
case "s390":
return []string{"-m31"}
case "s390x":
return []string{"-m64"}
} }
return nil return nil
} }
@ -765,7 +766,7 @@ func (p *Package) gccCmd() []string {
"-c", // do not link "-c", // do not link
"-xc", // input language is C "-xc", // input language is C
) )
if strings.Contains(c[0], "clang") { if p.GccIsClang {
c = append(c, c = append(c,
"-ferror-limit=0", "-ferror-limit=0",
// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
@ -780,7 +781,7 @@ func (p *Package) gccCmd() []string {
// incorrectly typed unsigned long. We work around that // incorrectly typed unsigned long. We work around that
// by disabling the builtin functions (this is safe as // by disabling the builtin functions (this is safe as
// it won't affect the actual compilation of the C code). // it won't affect the actual compilation of the C code).
// See: http://golang.org/issue/6506. // See: https://golang.org/issue/6506.
"-fno-builtin", "-fno-builtin",
) )
} }
@ -992,8 +993,8 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.goVoid = c.Ident("_Ctype_void") c.goVoid = c.Ident("_Ctype_void")
// Normally cgo translates void* to unsafe.Pointer, // Normally cgo translates void* to unsafe.Pointer,
// but for historical reasons -cdefs and -godefs use *byte instead. // but for historical reasons -godefs uses *byte instead.
if *cdefs || *godefs { if *godefs {
c.goVoidPtr = &ast.StarExpr{X: c.byte} c.goVoidPtr = &ast.StarExpr{X: c.byte}
} else { } else {
c.goVoidPtr = c.Ident("unsafe.Pointer") c.goVoidPtr = c.Ident("unsafe.Pointer")
@ -1045,7 +1046,7 @@ func (tr *TypeRepr) String() string {
return fmt.Sprintf(tr.Repr, tr.FormatArgs...) return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
} }
// Empty returns true if the result of String would be "". // Empty reports whether the result of String would be "".
func (tr *TypeRepr) Empty() bool { func (tr *TypeRepr) Empty() bool {
return len(tr.Repr) == 0 return len(tr.Repr) == 0
} }
@ -1334,8 +1335,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo", // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
// use that as the Go form for this typedef too, so that the typedef will be interchangeable // use that as the Go form for this typedef too, so that the typedef will be interchangeable
// with the base type. // with the base type.
// In -godefs and -cdefs mode, do this for all typedefs. // In -godefs mode, do this for all typedefs.
if isStructUnionClass(sub.Go) || *godefs || *cdefs { if isStructUnionClass(sub.Go) || *godefs {
t.Go = sub.Go t.Go = sub.Go
if isStructUnionClass(sub.Go) { if isStructUnionClass(sub.Go) {
@ -1397,7 +1398,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
name := c.Ident("_Ctype_" + s) name := c.Ident("_Ctype_" + s)
tt := *t tt := *t
typedef[name.Name] = &tt typedef[name.Name] = &tt
if !*godefs && !*cdefs { if !*godefs {
t.Go = name t.Go = name
} }
} }
@ -1543,14 +1544,16 @@ func (c *typeConv) intExpr(n int64) ast.Expr {
} }
// Add padding of given size to fld. // Add padding of given size to fld.
func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field { func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
n := len(fld) n := len(fld)
fld = fld[0 : n+1] fld = fld[0 : n+1]
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)} fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
return fld sizes = sizes[0 : n+1]
sizes[n] = size
return fld, sizes
} }
// Struct conversion: return Go and (6g) C syntax for type. // Struct conversion: return Go and (gc) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
// Minimum alignment for a struct is 1 byte. // Minimum alignment for a struct is 1 byte.
align = 1 align = 1
@ -1558,6 +1561,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
var buf bytes.Buffer var buf bytes.Buffer
buf.WriteString("struct {") buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
sizes := make([]int64, 0, 2*len(dt.Field)+1)
off := int64(0) off := int64(0)
// Rename struct fields that happen to be named Go keywords into // Rename struct fields that happen to be named Go keywords into
@ -1573,7 +1577,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
used[f.Name] = true used[f.Name] = true
} }
if !*godefs && !*cdefs { if !*godefs {
for cid, goid := range ident { for cid, goid := range ident {
if token.Lookup(goid).IsKeyword() { if token.Lookup(goid).IsKeyword() {
// Avoid keyword // Avoid keyword
@ -1593,19 +1597,19 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
anon := 0 anon := 0
for _, f := range dt.Field { for _, f := range dt.Field {
if f.ByteOffset > off { if f.ByteOffset > off {
fld = c.pad(fld, f.ByteOffset-off) fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
off = f.ByteOffset off = f.ByteOffset
} }
name := f.Name name := f.Name
ft := f.Type ft := f.Type
// In godefs or cdefs mode, if this field is a C11 // In godefs mode, if this field is a C11
// anonymous union then treat the first field in the // anonymous union then treat the first field in the
// union as the field in the struct. This handles // union as the field in the struct. This handles
// cases like the glibc <sys/resource.h> file; see // cases like the glibc <sys/resource.h> file; see
// issue 6677. // issue 6677.
if *godefs || *cdefs { if *godefs {
if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] { if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
name = st.Field[0].Name name = st.Field[0].Name
ident[name] = name ident[name] = name
@ -1635,14 +1639,12 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
talign = size talign = size
} }
if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs { if talign > 0 && f.ByteOffset%talign != 0 {
// Drop misaligned fields, the same way we drop integer bit fields. // Drop misaligned fields, the same way we drop integer bit fields.
// The goal is to make available what can be made available. // The goal is to make available what can be made available.
// Otherwise one bad and unneeded field in an otherwise okay struct // Otherwise one bad and unneeded field in an otherwise okay struct
// makes the whole program not compile. Much of the time these // makes the whole program not compile. Much of the time these
// structs are in system headers that cannot be corrected. // structs are in system headers that cannot be corrected.
// Exception: In -cdefs mode, we use #pragma pack, so misaligned
// fields should still work.
continue continue
} }
n := len(fld) n := len(fld)
@ -1653,6 +1655,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
ident[name] = name ident[name] = name
} }
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo} fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
sizes = sizes[0 : n+1]
sizes[n] = size
off += size off += size
buf.WriteString(t.C.String()) buf.WriteString(t.C.String())
buf.WriteString(" ") buf.WriteString(" ")
@ -1663,16 +1667,29 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
} }
} }
if off < dt.ByteSize { if off < dt.ByteSize {
fld = c.pad(fld, dt.ByteSize-off) fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
off = dt.ByteSize off = dt.ByteSize
} }
// If the last field in a non-zero-sized struct is zero-sized
// the compiler is going to pad it by one (see issue 9401).
// We can't permit that, because then the size of the Go
// struct will not be the same as the size of the C struct.
// Our only option in such a case is to remove the field,
// which means that it can not be referenced from Go.
for off > 0 && sizes[len(sizes)-1] == 0 {
n := len(sizes)
fld = fld[0 : n-1]
sizes = sizes[0 : n-1]
}
if off != dt.ByteSize { if off != dt.ByteSize {
fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize) fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
} }
buf.WriteString("}") buf.WriteString("}")
csyntax = buf.String() csyntax = buf.String()
if *godefs || *cdefs { if *godefs {
godefsFields(fld) godefsFields(fld)
} }
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
@ -1707,12 +1724,10 @@ func godefsFields(fld []*ast.Field) {
n.Name = "Pad_cgo_" + strconv.Itoa(npad) n.Name = "Pad_cgo_" + strconv.Itoa(npad)
npad++ npad++
} }
if !*cdefs {
n.Name = upper(n.Name) n.Name = upper(n.Name)
} }
} }
} }
}
// fieldPrefix returns the prefix that should be removed from all the // fieldPrefix returns the prefix that should be removed from all the
// field names when generating the C or Go code. For generated // field names when generating the C or Go code. For generated
@ -1721,9 +1736,6 @@ func godefsFields(fld []*ast.Field) {
// package syscall's data structures, we drop a common prefix // package syscall's data structures, we drop a common prefix
// (so sec, usec, which will get turned into Sec, Usec for exporting). // (so sec, usec, which will get turned into Sec, Usec for exporting).
func fieldPrefix(fld []*ast.Field) string { func fieldPrefix(fld []*ast.Field) string {
if *cdefs {
return ""
}
prefix := "" prefix := ""
for _, f := range fld { for _, f := range fld {
for _, n := range f.Names { for _, n := range f.Names {

View File

@ -114,173 +114,6 @@ func (p *Package) godefs(f *File, srcfile string) string {
return buf.String() return buf.String()
} }
// cdefs returns the output for -cdefs mode.
// The easiest way to do this is to translate the godefs Go to C.
func (p *Package) cdefs(f *File, srcfile string) string {
godefsOutput := p.godefs(f, srcfile)
lines := strings.Split(godefsOutput, "\n")
lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
for i, line := range lines {
lines[i] = strings.TrimSpace(line)
}
var out bytes.Buffer
printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
didTypedef := false
for i := 0; i < len(lines); i++ {
line := lines[i]
// Delete
// package x
if strings.HasPrefix(line, "package ") {
continue
}
// Convert
// const (
// A = 1
// B = 2
// )
//
// to
//
// enum {
// A = 1,
// B = 2,
// };
if line == "const (" {
printf("enum {\n")
for i++; i < len(lines) && lines[i] != ")"; i++ {
line = lines[i]
if line != "" {
printf("\t%s,", line)
}
printf("\n")
}
printf("};\n")
continue
}
// Convert
// const A = 1
// to
// enum { A = 1 };
if strings.HasPrefix(line, "const ") {
printf("enum { %s };\n", line[len("const "):])
continue
}
// On first type definition, typedef all the structs
// in case there are dependencies between them.
if !didTypedef && strings.HasPrefix(line, "type ") {
didTypedef = true
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
printf("typedef struct %s %s;\n", s, s)
}
}
printf("\n")
printf("#pragma pack on\n")
printf("\n")
}
// Convert
// type T struct {
// X int64
// Y *int32
// Z [4]byte
// }
//
// to
//
// struct T {
// int64 X;
// int32 *Y;
// byte Z[4];
// }
if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
if len(lines) > i+1 && lines[i+1] == "}" {
// do not output empty struct
i++
continue
}
s := line[len("type ") : len(line)-len(" struct {")]
printf("struct %s {\n", s)
for i++; i < len(lines) && lines[i] != "}"; i++ {
line := lines[i]
if line != "" {
f := strings.Fields(line)
if len(f) != 2 {
fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
nerrors++
continue
}
printf("\t%s;", cdecl(f[0], f[1]))
}
printf("\n")
}
printf("};\n")
continue
}
// Convert
// type T int
// to
// typedef int T;
if strings.HasPrefix(line, "type ") {
f := strings.Fields(line[len("type "):])
if len(f) != 2 {
fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
nerrors++
continue
}
printf("typedef\t%s;\n", cdecl(f[0], f[1]))
continue
}
printf("%s\n", line)
}
if didTypedef {
printf("\n")
printf("#pragma pack off\n")
}
return out.String()
}
// cdecl returns the C declaration for the given Go name and type.
// It only handles the specific cases necessary for converting godefs output.
func cdecl(name, typ string) string {
// X *[0]byte -> X *void
if strings.HasPrefix(typ, "*[0]") {
typ = "*void"
}
// X [4]byte -> X[4] byte
for strings.HasPrefix(typ, "[") {
i := strings.Index(typ, "]") + 1
name = name + typ[:i]
typ = typ[i:]
}
// X *byte -> *X byte
for strings.HasPrefix(typ, "*") {
name = "*" + name
typ = typ[1:]
}
// X T -> T X
// Handle the special case: 'unsafe.Pointer' is 'void *'
if typ == "unsafe.Pointer" {
typ = "void"
name = "*" + name
}
return typ + "\t" + name
}
var gofmtBuf bytes.Buffer var gofmtBuf bytes.Buffer
// gofmt returns the gofmt-formatted string for an AST node. // gofmt returns the gofmt-formatted string for an AST node.

View File

@ -6,7 +6,7 @@
// TODO(rsc): // TODO(rsc):
// Emit correct line number annotations. // Emit correct line number annotations.
// Make 6g understand the annotations. // Make gc understand the annotations.
package main package main
@ -33,6 +33,7 @@ type Package struct {
PtrSize int64 PtrSize int64
IntSize int64 IntSize int64
GccOptions []string GccOptions []string
GccIsClang bool
CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS) CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
Written map[string]bool Written map[string]bool
Name map[string]*Name // accumulated Name from Files Name map[string]*Name // accumulated Name from Files
@ -87,7 +88,7 @@ type Name struct {
Const string // constant definition Const string // constant definition
} }
// IsVar returns true if Kind is either "var" or "fpvar" // IsVar reports whether Kind is either "var" or "fpvar"
func (n *Name) IsVar() bool { func (n *Name) IsVar() bool {
return n.Kind == "var" || n.Kind == "fpvar" return n.Kind == "var" || n.Kind == "fpvar"
} }
@ -98,6 +99,7 @@ func (n *Name) IsVar() bool {
type ExpFunc struct { type ExpFunc struct {
Func *ast.FuncDecl Func *ast.FuncDecl
ExpName string // name to use from C ExpName string // name to use from C
Doc string
} }
// A TypeRepr contains the string representation of a type. // A TypeRepr contains the string representation of a type.
@ -174,15 +176,18 @@ var cPrefix string
var fset = token.NewFileSet() var fset = token.NewFileSet()
var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file") var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
var dynout = flag.String("dynout", "", "write -dynobj output to this file") var dynout = flag.String("dynout", "", "write -dynimport output to this file")
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode") var dynpackage = flag.String("dynpackage", "main", "set Go package for -dynimport output")
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in -dynimport mode")
// These flags are for bootstrapping a new Go implementation, // This flag is for bootstrapping a new Go implementation,
// to generate Go and C headers that match the data layout and // to generate Go types that match the data layout and
// constant values used in the host's C libraries and system calls. // constant values used in the host's C libraries and system calls.
var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output") var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
var objDir = flag.String("objdir", "", "object directory") var objDir = flag.String("objdir", "", "object directory")
var importPath = flag.String("importpath", "", "import path of package being built (for comments in generated files)")
var exportHeader = flag.String("exportheader", "", "where to write export header if any exported functions")
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo") var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo") var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
@ -208,12 +213,7 @@ func main() {
return return
} }
if *godefs && *cdefs { if *godefs {
fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
os.Exit(2)
}
if *godefs || *cdefs {
// Generating definitions pulled from header files, // Generating definitions pulled from header files,
// to be checked into Go repositories. // to be checked into Go repositories.
// Line numbers are just noise. // Line numbers are just noise.
@ -305,14 +305,12 @@ func main() {
p.Record(f) p.Record(f)
if *godefs { if *godefs {
os.Stdout.WriteString(p.godefs(f, input)) os.Stdout.WriteString(p.godefs(f, input))
} else if *cdefs {
os.Stdout.WriteString(p.cdefs(f, input))
} else { } else {
p.writeOutput(f, input) p.writeOutput(f, input)
} }
} }
if !*godefs && !*cdefs { if !*godefs {
p.writeDefs() p.writeDefs()
} }
if nerrors > 0 { if nerrors > 0 {

View File

@ -13,6 +13,7 @@ import (
"go/ast" "go/ast"
"go/printer" "go/printer"
"go/token" "go/token"
"io"
"os" "os"
"sort" "sort"
"strings" "strings"
@ -20,11 +21,17 @@ import (
var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8} var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
// writeDefs creates output files to be compiled by 6g, 6c, and gcc. // writeDefs creates output files to be compiled by gc and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeDefs() { func (p *Package) writeDefs() {
fgo2 := creat(*objDir + "_cgo_gotypes.go") var fgo2, fc io.Writer
fc := creat(*objDir + "_cgo_defun.c") f := creat(*objDir + "_cgo_gotypes.go")
defer f.Close()
fgo2 = f
if *gccgo {
f := creat(*objDir + "_cgo_defun.c")
defer f.Close()
fc = f
}
fm := creat(*objDir + "_cgo_main.c") fm := creat(*objDir + "_cgo_main.c")
var gccgoInit bytes.Buffer var gccgoInit bytes.Buffer
@ -34,7 +41,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " ")) fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
if k == "LDFLAGS" && !*gccgo { if k == "LDFLAGS" && !*gccgo {
for _, arg := range v { for _, arg := range v {
fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg) fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
} }
} }
} }
@ -44,14 +51,17 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "int main() { return 0; }\n") fmt.Fprintf(fm, "int main() { return 0; }\n")
if *importRuntimeCgo { if *importRuntimeCgo {
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n") fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done() { }\n")
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n") fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else { } else {
// If we're not importing runtime/cgo, we *are* runtime/cgo, // If we're not importing runtime/cgo, we *are* runtime/cgo,
// which provides crosscall2. We just need a prototype. // which provides these functions. We just need a prototype.
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n") fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done();\n")
} }
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
// Write second Go output: definitions of _C_xxx. // Write second Go output: definitions of _C_xxx.
// In a separate file so that the import of "unsafe" does not // In a separate file so that the import of "unsafe" does not
@ -68,6 +78,13 @@ func (p *Package) writeDefs() {
} }
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
if !*gccgo {
fmt.Fprintf(fgo2, "//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse\n")
fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n")
fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n")
fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n")
}
typedefNames := make([]string, 0, len(typedef)) typedefNames := make([]string, 0, len(typedef))
for name := range typedef { for name := range typedef {
typedefNames = append(typedefNames, name) typedefNames = append(typedefNames, name)
@ -88,7 +105,6 @@ func (p *Package) writeDefs() {
if *gccgo { if *gccgo {
fmt.Fprint(fc, p.cPrologGccgo()) fmt.Fprint(fc, p.cPrologGccgo())
} else { } else {
fmt.Fprint(fc, cProlog)
fmt.Fprint(fgo2, goProlog) fmt.Fprint(fgo2, goProlog)
} }
@ -102,44 +118,44 @@ func (p *Package) writeDefs() {
} }
if !cVars[n.C] { if !cVars[n.C] {
if *gccgo {
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
} else {
fmt.Fprintf(fm, "extern char %s[];\n", n.C) fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
if !*gccgo { fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C) fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
} }
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
cVars[n.C] = true cVars[n.C] = true
} }
var amp string
var node ast.Node var node ast.Node
if n.Kind == "var" { if n.Kind == "var" {
amp = "&"
node = &ast.StarExpr{X: n.Type.Go} node = &ast.StarExpr{X: n.Type.Go}
} else if n.Kind == "fpvar" { } else if n.Kind == "fpvar" {
node = n.Type.Go node = n.Type.Go
if *gccgo {
amp = "&"
}
} else { } else {
panic(fmt.Errorf("invalid var kind %q", n.Kind)) panic(fmt.Errorf("invalid var kind %q", n.Kind))
} }
if *gccgo { if *gccgo {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C) fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
} else {
fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
}
fmt.Fprintf(fc, "\n") fmt.Fprintf(fc, "\n")
}
fmt.Fprintf(fgo2, "var %s ", n.Mangle) fmt.Fprintf(fgo2, "var %s ", n.Mangle)
conf.Fprint(fgo2, fset, node) conf.Fprint(fgo2, fset, node)
if !*gccgo {
fmt.Fprintf(fgo2, " = (")
conf.Fprint(fgo2, fset, node)
fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
}
fmt.Fprintf(fgo2, "\n") fmt.Fprintf(fgo2, "\n")
} }
if *gccgo {
fmt.Fprintf(fc, "\n") fmt.Fprintf(fc, "\n")
}
for _, key := range nameKeys(p.Name) { for _, key := range nameKeys(p.Name) {
n := p.Name[key] n := p.Name[key]
@ -152,14 +168,37 @@ func (p *Package) writeDefs() {
for _, key := range nameKeys(p.Name) { for _, key := range nameKeys(p.Name) {
n := p.Name[key] n := p.Name[key]
if n.FuncType != nil { if n.FuncType != nil {
p.writeDefsFunc(fc, fgo2, n) p.writeDefsFunc(fgo2, n)
} }
} }
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
if *gccgo { if *gccgo {
p.writeGccgoExports(fgo2, fc, fm) p.writeGccgoExports(fgo2, fm, fgcc, fgcch)
} else { } else {
p.writeExports(fgo2, fc, fm) p.writeExports(fgo2, fm, fgcc, fgcch)
}
if err := fgcc.Close(); err != nil {
fatalf("%s", err)
}
if err := fgcch.Close(); err != nil {
fatalf("%s", err)
}
if *exportHeader != "" && len(p.ExpFunc) > 0 {
fexp := creat(*exportHeader)
fgcch, err := os.Open(*objDir + "_cgo_export.h")
if err != nil {
fatalf("%s", err)
}
_, err = io.Copy(fexp, fgcch)
if err != nil {
fatalf("%s", err)
}
if err = fexp.Close(); err != nil {
fatalf("%s", err)
}
} }
init := gccgoInit.String() init := gccgoInit.String()
@ -169,9 +208,6 @@ func (p *Package) writeDefs() {
fmt.Fprint(fc, init) fmt.Fprint(fc, init)
fmt.Fprintln(fc, "}") fmt.Fprintln(fc, "}")
} }
fgo2.Close()
fc.Close()
} }
func dynimport(obj string) { func dynimport(obj string) {
@ -184,13 +220,15 @@ func dynimport(obj string) {
stdout = f stdout = f
} }
fmt.Fprintf(stdout, "package %s\n", *dynpackage)
if f, err := elf.Open(obj); err == nil { if f, err := elf.Open(obj); err == nil {
if *dynlinker { if *dynlinker {
// Emit the cgo_dynamic_linker line. // Emit the cgo_dynamic_linker line.
if sec := f.Section(".interp"); sec != nil { if sec := f.Section(".interp"); sec != nil {
if data, err := sec.Data(); err == nil && len(data) > 1 { if data, err := sec.Data(); err == nil && len(data) > 1 {
// skip trailing \0 in data // skip trailing \0 in data
fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1])) fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
} }
} }
} }
@ -203,14 +241,14 @@ func dynimport(obj string) {
if s.Version != "" { if s.Version != "" {
targ += "#" + s.Version targ += "#" + s.Version
} }
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
} }
lib, err := f.ImportedLibraries() lib, err := f.ImportedLibraries()
if err != nil { if err != nil {
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
} }
for _, l := range lib { for _, l := range lib {
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l) fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
} }
return return
} }
@ -224,14 +262,14 @@ func dynimport(obj string) {
if len(s) > 0 && s[0] == '_' { if len(s) > 0 && s[0] == '_' {
s = s[1:] s = s[1:]
} }
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "") fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
} }
lib, err := f.ImportedLibraries() lib, err := f.ImportedLibraries()
if err != nil { if err != nil {
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
} }
for _, l := range lib { for _, l := range lib {
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l) fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
} }
return return
} }
@ -244,7 +282,7 @@ func dynimport(obj string) {
for _, s := range sym { for _, s := range sym {
ss := strings.Split(s, ":") ss := strings.Split(s, ":")
name := strings.Split(ss[0], "@")[0] name := strings.Split(ss[0], "@")[0]
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
} }
return return
} }
@ -252,10 +290,10 @@ func dynimport(obj string) {
fatalf("cannot parse %s as ELF, Mach-O or PE", obj) fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
} }
// Construct a gcc struct matching the 6c argument frame. // Construct a gcc struct matching the gc argument frame.
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
// These assumptions are checked by the gccProlog. // These assumptions are checked by the gccProlog.
// Also assumes that 6c convention is to word-align the // Also assumes that gc convention is to word-align the
// input and output parameters. // input and output parameters.
func (p *Package) structType(n *Name) (string, int64) { func (p *Package) structType(n *Name) (string, int64) {
var buf bytes.Buffer var buf bytes.Buffer
@ -304,7 +342,7 @@ func (p *Package) structType(n *Name) (string, int64) {
return buf.String(), off return buf.String(), off
} }
func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
name := n.Go name := n.Go
gtype := n.FuncType.Go gtype := n.FuncType.Go
void := gtype.Results == nil || len(gtype.Results.List) == 0 void := gtype.Results == nil || len(gtype.Results.List) == 0
@ -396,11 +434,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
return return
} }
// C wrapper calls into gcc, passing a pointer to the argument frame. // Wrapper calls into gcc, passing a pointer to the argument frame.
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname) fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
fmt.Fprintf(fc, "void %s(void*);\n", cname) fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
fmt.Fprintf(fc, "#pragma dataflag NOPTR\n") fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname) fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
nret := 0 nret := 0
if !void { if !void {
@ -412,7 +450,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
} }
fmt.Fprint(fgo2, "\n") fmt.Fprint(fgo2, "\n")
fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
conf.Fprint(fgo2, fset, d) conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n") fmt.Fprint(fgo2, " {\n")
@ -428,16 +465,20 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
if n.AddError { if n.AddError {
prefix = "errno := " prefix = "errno := "
} }
fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg) fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg)
if n.AddError { if n.AddError {
fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
} }
fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
for i := range d.Type.Params.List {
fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
}
fmt.Fprintf(fgo2, "\t}\n")
fmt.Fprintf(fgo2, "\treturn\n") fmt.Fprintf(fgo2, "\treturn\n")
fmt.Fprintf(fgo2, "}\n") fmt.Fprintf(fgo2, "}\n")
} }
// writeOutput creates stubs for a specific source file to be compiled by 6g // writeOutput creates stubs for a specific source file to be compiled by gc
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeOutput(f *File, srcfile string) { func (p *Package) writeOutput(f *File, srcfile string) {
base := srcfile base := srcfile
if strings.HasSuffix(base, ".go") { if strings.HasSuffix(base, ".go") {
@ -454,7 +495,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
conf.Fprint(fgo1, fset, f.AST) conf.Fprint(fgo1, fset, f.AST)
// While we process the vars and funcs, also write 6c and gcc output. // While we process the vars and funcs, also write gcc output.
// Gcc output starts with the preamble. // Gcc output starts with the preamble.
fmt.Fprintf(fgcc, "%s\n", f.Preamble) fmt.Fprintf(fgcc, "%s\n", f.Preamble)
fmt.Fprintf(fgcc, "%s\n", gccProlog) fmt.Fprintf(fgcc, "%s\n", gccProlog)
@ -516,7 +557,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
if n.AddError { if n.AddError {
fmt.Fprintf(fgcc, "\terrno = 0;\n") fmt.Fprintf(fgcc, "\terrno = 0;\n")
} }
// We're trying to write a gcc struct that matches 6c/8c/5c's layout. // We're trying to write a gcc struct that matches gc's layout.
// Use packed attribute to force no padding in this struct in case // Use packed attribute to force no padding in this struct in case
// gcc has different packing requirements. // gcc has different packing requirements.
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
@ -612,13 +653,13 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
} }
// packedAttribute returns host compiler struct attribute that will be // packedAttribute returns host compiler struct attribute that will be
// used to match 6c/8c/5c's struct layout. For example, on 386 Windows, // used to match gc's struct layout. For example, on 386 Windows,
// gcc wants to 8-align int64s, but 8c does not. // gcc wants to 8-align int64s, but gc does not.
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
// and http://golang.org/issue/5603. // and https://golang.org/issue/5603.
func (p *Package) packedAttribute() string { func (p *Package) packedAttribute() string {
s := "__attribute__((__packed__" s := "__attribute__((__packed__"
if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") { if !p.GccIsClang && (goarch == "amd64" || goarch == "386") {
s += ", __gcc_struct__" s += ", __gcc_struct__"
} }
return s + "))" return s + "))"
@ -626,23 +667,19 @@ func (p *Package) packedAttribute() string {
// Write out the various stubs we need to support functions exported // Write out the various stubs we need to support functions exported
// from Go so that they are callable from C. // from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) { func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fgcc := creat(*objDir + "_cgo_export.c") p.writeExportHeader(fgcch)
fgcch := creat(*objDir + "_cgo_export.h")
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n") fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int), void *, int);\n")
fmt.Fprintf(fgcc, "extern void _cgo_wait_runtime_init_done();\n\n")
for _, exp := range p.ExpFunc { for _, exp := range p.ExpFunc {
fn := exp.Func fn := exp.Func
// Construct a gcc struct matching the 6c argument and // Construct a gcc struct matching the gc argument and
// result frame. The gcc struct will be compiled with // result frame. The gcc struct will be compiled with
// __attribute__((packed)) so all padding must be accounted // __attribute__((packed)) so all padding must be accounted
// for explicitly. // for explicitly.
@ -728,11 +765,16 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
}) })
s += ")" s += ")"
if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
}
fmt.Fprintf(fgcch, "\nextern %s;\n", s) fmt.Fprintf(fgcch, "\nextern %s;\n", s)
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName) fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgcc, "\n%s\n", s) fmt.Fprintf(fgcc, "\n%s\n", s)
fmt.Fprintf(fgcc, "{\n") fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\t_cgo_wait_runtime_init_done();\n")
fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
@ -758,20 +800,21 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
} }
fmt.Fprintf(fgcc, "}\n") fmt.Fprintf(fgcc, "}\n")
// Build the wrapper function compiled by 6c/8c // Build the wrapper function compiled by gc.
goname := exp.Func.Name.Name goname := exp.Func.Name.Name
if fn.Recv != nil { if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
} }
fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname) fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname) fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n") fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName) fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "{\n") fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname) // The indirect here is converting from a Go function pointer to a C function pointer.
fmt.Fprintf(fc, "}\n") fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
fmt.Fprintf(fgo2, "}\n")
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
@ -814,23 +857,20 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, "}\n") fmt.Fprint(fgo2, "}\n")
} }
} }
fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
} }
// Write out the C header allowing C code to call exported gccgo functions. // Write out the C header allowing C code to call exported gccgo functions.
func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) { func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
gccgoSymbolPrefix := p.gccgoSymbolPrefix() gccgoSymbolPrefix := p.gccgoSymbolPrefix()
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") p.writeExportHeader(fgcch)
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n") fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
for _, exp := range p.ExpFunc { for _, exp := range p.ExpFunc {
fn := exp.Func fn := exp.Func
@ -851,6 +891,7 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
}) })
default: default:
// Declare a result struct. // Declare a result struct.
fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName) fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
forFieldList(fntype.Results, forFieldList(fntype.Results,
func(i int, atype ast.Expr) { func(i int, atype ast.Expr) {
@ -880,6 +921,10 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprintf(cdeclBuf, ")") fmt.Fprintf(cdeclBuf, ")")
cParams := cdeclBuf.String() cParams := cdeclBuf.String()
if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
}
// We need to use a name that will be exported by the // We need to use a name that will be exported by the
// Go code; otherwise gccgo will make it static and we // Go code; otherwise gccgo will make it static and we
// will not be able to link against it from the C // will not be able to link against it from the C
@ -900,6 +945,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "\n") fmt.Fprint(fgcc, "\n")
fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams) fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
fmt.Fprint(fgcc, "\t") fmt.Fprint(fgcc, "\t")
if resultCount > 0 { if resultCount > 0 {
fmt.Fprint(fgcc, "return ") fmt.Fprint(fgcc, "return ")
@ -919,7 +966,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "}\n") fmt.Fprint(fgcc, "}\n")
// Dummy declaration for _cgo_main.c // Dummy declaration for _cgo_main.c
fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams) fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
fmt.Fprint(fm, "\n")
// For gccgo we use a wrapper function in Go, in order // For gccgo we use a wrapper function in Go, in order
// to call CgocallBack and CgocallBackDone. // to call CgocallBack and CgocallBackDone.
@ -974,6 +1022,24 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, ")\n") fmt.Fprint(fgo2, ")\n")
fmt.Fprint(fgo2, "}\n") fmt.Fprint(fgo2, "}\n")
} }
fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// writeExportHeader writes out the start of the _cgo_export.h file.
func (p *Package) writeExportHeader(fgcch io.Writer) {
fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n")
pkg := *importPath
if pkg == "" {
pkg = p.PackagePath
}
fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg)
fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments. */\n\n")
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments. */\n\n")
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
} }
// Return the package prefix when using gccgo. // Return the package prefix when using gccgo.
@ -1164,60 +1230,39 @@ char *CString(_GoString_);
void *_CMalloc(size_t); void *_CMalloc(size_t);
` `
const cProlog = `
#include "runtime.h"
#include "cgocall.h"
#include "textflag.h"
#pragma dataflag NOPTR
static void *cgocall_errno = runtime·cgocall_errno;
#pragma dataflag NOPTR
void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
#pragma dataflag NOPTR
static void *runtime_gostring = runtime·gostring;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostring = &runtime_gostring;
#pragma dataflag NOPTR
static void *runtime_gostringn = runtime·gostringn;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostringn = &runtime_gostringn;
#pragma dataflag NOPTR
static void *runtime_gobytes = runtime·gobytes;
#pragma dataflag NOPTR
void *·_cgo_runtime_gobytes = &runtime_gobytes;
#pragma dataflag NOPTR
static void *runtime_cmalloc = runtime·cmalloc;
#pragma dataflag NOPTR
void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
void ·_Cerrno(void*, int32);
`
const goProlog = ` const goProlog = `
var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32 //go:linkname _cgo_runtime_cgocall runtime.cgocall
var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
` `
const goStringDef = ` const goStringDef = `
var _cgo_runtime_gostring func(*_Ctype_char) string //go:linkname _cgo_runtime_gostring runtime.gostring
func _cgo_runtime_gostring(*_Ctype_char) string
func _Cfunc_GoString(p *_Ctype_char) string { func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p) return _cgo_runtime_gostring(p)
} }
` `
const goStringNDef = ` const goStringNDef = `
var _cgo_runtime_gostringn func(*_Ctype_char, int) string //go:linkname _cgo_runtime_gostringn runtime.gostringn
func _cgo_runtime_gostringn(*_Ctype_char, int) string
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string { func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l)) return _cgo_runtime_gostringn(p, int(l))
} }
` `
const goBytesDef = ` const goBytesDef = `
var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte //go:linkname _cgo_runtime_gobytes runtime.gobytes
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l)) return _cgo_runtime_gobytes(p, int(l))
} }
@ -1310,6 +1355,11 @@ func (p *Package) gccExportHeaderProlog() string {
} }
const gccExportHeaderProlog = ` const gccExportHeaderProlog = `
/* Start of boilerplate cgo prologue. */
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8; typedef signed char GoInt8;
typedef unsigned char GoUint8; typedef unsigned char GoUint8;
typedef short GoInt16; typedef short GoInt16;
@ -1326,9 +1376,44 @@ typedef double GoFloat64;
typedef __complex float GoComplex64; typedef __complex float GoComplex64;
typedef __complex double GoComplex128; typedef __complex double GoComplex128;
// static assertion to make sure the file is being used on architecture
// at least with matching size of GoInt.
typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];
typedef struct { char *p; GoInt n; } GoString; typedef struct { char *p; GoInt n; } GoString;
typedef void *GoMap; typedef void *GoMap;
typedef void *GoChan; typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface; typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
`
// gccExportHeaderEpilog goes at the end of the generated header file.
const gccExportHeaderEpilog = `
#ifdef __cplusplus
}
#endif
`
// gccgoExportFileProlog is written to the _cgo_export.c file when
// using gccgo.
// We use weak declarations, and test the addresses, so that this code
// works with older versions of gccgo.
const gccgoExportFileProlog = `
extern _Bool runtime_iscgo __attribute__ ((weak));
static void GoInit(void) __attribute__ ((constructor));
static void GoInit(void) {
if(&runtime_iscgo)
runtime_iscgo = 1;
}
extern void _cgo_wait_runtime_init_done() __attribute__ ((weak));
` `

View File

@ -55,7 +55,7 @@ func error_(pos token.Pos, msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "\n")
} }
// isName returns true if s is a valid C identifier // isName reports whether s is a valid C identifier
func isName(s string) bool { func isName(s string) bool {
for i, v := range s { for i, v := range s {
if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') { if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') {

1482
libgo/go/cmd/go/alldocs.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,11 +17,19 @@ import (
var errHTTP = errors.New("no http in bootstrap go command") var errHTTP = errors.New("no http in bootstrap go command")
type httpError struct {
statusCode int
}
func (e *httpError) Error() string {
panic("unreachable")
}
func httpGET(url string) ([]byte, error) { func httpGET(url string) ([]byte, error) {
return nil, errHTTP return nil, errHTTP
} }
func httpsOrHTTP(importPath string) (string, io.ReadCloser, error) { func httpsOrHTTP(importPath string, security securityMode) (string, io.ReadCloser, error) {
return "", nil, errHTTP return "", nil, errHTTP
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,6 @@ func mkEnv() []envVar {
env := []envVar{ env := []envVar{
{"GOARCH", goarch}, {"GOARCH", goarch},
{"GOBIN", gobin}, {"GOBIN", gobin},
{"GOCHAR", archChar},
{"GOEXE", exeSuffix}, {"GOEXE", exeSuffix},
{"GOHOSTARCH", runtime.GOARCH}, {"GOHOSTARCH", runtime.GOARCH},
{"GOHOSTOS", runtime.GOOS}, {"GOHOSTOS", runtime.GOOS},
@ -45,6 +44,7 @@ func mkEnv() []envVar {
{"GORACE", os.Getenv("GORACE")}, {"GORACE", os.Getenv("GORACE")},
{"GOROOT", goroot}, {"GOROOT", goroot},
{"GOTOOLDIR", toolDir}, {"GOTOOLDIR", toolDir},
{"GO15VENDOREXPERIMENT", os.Getenv("GO15VENDOREXPERIMENT")},
// disable escape codes in clang errors // disable escape codes in clang errors
{"TERM", "dumb"}, {"TERM", "dumb"},

View File

@ -11,7 +11,7 @@ var cmdFix = &Command{
Long: ` Long: `
Fix runs the Go fix command on the packages named by the import paths. Fix runs the Go fix command on the packages named by the import paths.
For more about fix, see 'godoc fix'. For more about fix, see 'go doc cmd/fix'.
For more about specifying packages, see 'go help packages'. For more about specifying packages, see 'go help packages'.
To run fix with specific options, run 'go tool fix'. To run fix with specific options, run 'go tool fix'.
@ -25,6 +25,6 @@ func runFix(cmd *Command, args []string) {
// Use pkg.gofiles instead of pkg.Dir so that // Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package, // the command only applies to this package,
// not to packages in subdirectories. // not to packages in subdirectories.
run(stringList(tool("fix"), relPaths(pkg.allgofiles))) run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
} }
} }

View File

@ -4,6 +4,11 @@
package main package main
import (
"os"
"path/filepath"
)
func init() { func init() {
addBuildFlagsNX(cmdFmt) addBuildFlagsNX(cmdFmt)
} }
@ -16,7 +21,7 @@ var cmdFmt = &Command{
Fmt runs the command 'gofmt -l -w' on the packages named Fmt runs the command 'gofmt -l -w' on the packages named
by the import paths. It prints the names of the files that are modified. by the import paths. It prints the names of the files that are modified.
For more about gofmt, see 'godoc gofmt'. For more about gofmt, see 'go doc cmd/gofmt'.
For more about specifying packages, see 'go help packages'. For more about specifying packages, see 'go help packages'.
The -n flag prints commands that would be executed. The -n flag prints commands that would be executed.
@ -29,10 +34,31 @@ See also: go fix, go vet.
} }
func runFmt(cmd *Command, args []string) { func runFmt(cmd *Command, args []string) {
gofmt := gofmtPath()
for _, pkg := range packages(args) { for _, pkg := range packages(args) {
// Use pkg.gofiles instead of pkg.Dir so that // Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package, // the command only applies to this package,
// not to packages in subdirectories. // not to packages in subdirectories.
run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles))) run(stringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
} }
} }
func gofmtPath() string {
gofmt := "gofmt"
if toolIsWindows {
gofmt += toolWindowsExtension
}
gofmtPath := filepath.Join(gobin, gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
gofmtPath = filepath.Join(goroot, "bin", gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
// fallback to looking for gofmt in $PATH
return "gofmt"
}

View File

@ -13,11 +13,11 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8"
) )
var cmdGenerate = &Command{ var cmdGenerate = &Command{
@ -62,8 +62,12 @@ Go generate sets several variables when it runs the generator:
The execution operating system (linux, windows, etc.) The execution operating system (linux, windows, etc.)
$GOFILE $GOFILE
The base name of the file. The base name of the file.
$GOLINE
The line number of the directive in the source file.
$GOPACKAGE $GOPACKAGE
The name of the package of the file containing the directive. The name of the package of the file containing the directive.
$DOLLAR
A dollar sign.
Other than variable substitution and quoted-string evaluation, no Other than variable substitution and quoted-string evaluation, no
special processing such as "globbing" is performed on the command special processing such as "globbing" is performed on the command
@ -106,9 +110,10 @@ The generator is run in the package's source directory.
Go generate accepts one specific flag: Go generate accepts one specific flag:
-run="" -run=""
TODO: This flag is unimplemented. if non-empty, specifies a regular expression to select
if non-empty, specifies a regular expression to directives whose full original source text (excluding
select directives whose command matches the expression. any trailing spaces and final newline) matches the
expression.
It also accepts the standard build flags -v, -n, and -x. It also accepts the standard build flags -v, -n, and -x.
The -v flag prints the names of packages and files as they are The -v flag prints the names of packages and files as they are
@ -120,7 +125,10 @@ For more about specifying packages, see 'go help packages'.
`, `,
} }
var generateRunFlag string // generate -run flag var (
generateRunFlag string // generate -run flag
generateRunRE *regexp.Regexp // compiled expression for -run
)
func init() { func init() {
addBuildFlags(cmdGenerate) addBuildFlags(cmdGenerate)
@ -128,6 +136,13 @@ func init() {
} }
func runGenerate(cmd *Command, args []string) { func runGenerate(cmd *Command, args []string) {
if generateRunFlag != "" {
var err error
generateRunRE, err = regexp.Compile(generateRunFlag)
if err != nil {
log.Fatalf("generate: %s", err)
}
}
// Even if the arguments are .go files, this loop suffices. // Even if the arguments are .go files, this loop suffices.
for _, pkg := range packages(args) { for _, pkg := range packages(args) {
for _, file := range pkg.gofiles { for _, file := range pkg.gofiles {
@ -163,7 +178,7 @@ type Generator struct {
file string // base name of file. file string // base name of file.
pkg string pkg string
commands map[string][]string commands map[string][]string
lineNum int lineNum int // current line number.
} }
// run runs the generators in the current file. // run runs the generators in the current file.
@ -221,6 +236,11 @@ func (g *Generator) run() (ok bool) {
if !isGoGenerate(buf) { if !isGoGenerate(buf) {
continue continue
} }
if generateRunFlag != "" {
if !generateRunRE.Match(bytes.TrimSpace(buf)) {
continue
}
}
words := g.split(string(buf)) words := g.split(string(buf))
if len(words) == 0 { if len(words) == 0 {
@ -306,7 +326,7 @@ Words:
} }
// Substitute environment variables. // Substitute environment variables.
for i, word := range words { for i, word := range words {
words[i] = g.expandEnv(word) words[i] = os.Expand(word, g.expandVar)
} }
return words return words
} }
@ -322,38 +342,25 @@ func (g *Generator) errorf(format string, args ...interface{}) {
panic(stop) panic(stop)
} }
// expandEnv expands any $XXX invocations in word. // expandVar expands the $XXX invocation in word. It is called
func (g *Generator) expandEnv(word string) string { // by os.Expand.
if !strings.ContainsRune(word, '$') { func (g *Generator) expandVar(word string) string {
return word switch word {
}
var buf bytes.Buffer
var w int
var r rune
for i := 0; i < len(word); i += w {
r, w = utf8.DecodeRuneInString(word[i:])
if r != '$' {
buf.WriteRune(r)
continue
}
w += g.identLength(word[i+w:])
envVar := word[i+1 : i+w]
var sub string
switch envVar {
case "GOARCH": case "GOARCH":
sub = runtime.GOARCH return buildContext.GOARCH
case "GOOS": case "GOOS":
sub = runtime.GOOS return buildContext.GOOS
case "GOFILE": case "GOFILE":
sub = g.file return g.file
case "GOLINE":
return fmt.Sprint(g.lineNum)
case "GOPACKAGE": case "GOPACKAGE":
sub = g.pkg return g.pkg
case "DOLLAR":
return "$"
default: default:
sub = os.Getenv(envVar) return os.Getenv(word)
} }
buf.WriteString(sub)
}
return buf.String()
} }
// identLength returns the length of the identifier beginning the string. // identLength returns the length of the identifier beginning the string.
@ -395,7 +402,7 @@ func (g *Generator) exec(words []string) {
"GOFILE=" + g.file, "GOFILE=" + g.file,
"GOPACKAGE=" + g.pkg, "GOPACKAGE=" + g.pkg,
} }
cmd.Env = mergeEnvLists(env, os.Environ()) cmd.Env = mergeEnvLists(env, origEnv)
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
g.errorf("running %q: %s", words[0], err) g.errorf("running %q: %s", words[0], err)

View File

@ -26,6 +26,7 @@ var splitTests = []splitTest{
{"$GOPACKAGE", []string{"sys"}}, {"$GOPACKAGE", []string{"sys"}},
{"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}}, {"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}},
{"/$XXNOTDEFINED/", []string{"//"}}, {"/$XXNOTDEFINED/", []string{"//"}},
{"/$DOLLAR/", []string{"/$/"}},
{"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}}, {"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}},
} }

View File

@ -16,7 +16,7 @@ import (
) )
var cmdGet = &Command{ var cmdGet = &Command{
UsageLine: "get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]", UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
Short: "download and install packages and dependencies", Short: "download and install packages and dependencies",
Long: ` Long: `
Get downloads and installs the packages named by the import paths, Get downloads and installs the packages named by the import paths,
@ -33,6 +33,9 @@ of the original.
The -fix flag instructs get to run the fix tool on the downloaded packages The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code. before resolving dependencies or building the code.
The -insecure flag permits fetching from repositories and resolving
custom domains using insecure schemes such as HTTP. Use with caution.
The -t flag instructs get to also download the packages required to build The -t flag instructs get to also download the packages required to build
the tests for the specified packages. the tests for the specified packages.
@ -48,6 +51,10 @@ rule is that if the local installation is running version "go1", get
searches for a branch or tag named "go1". If no such version exists it searches for a branch or tag named "go1". If no such version exists it
retrieves the most recent version of the package. retrieves the most recent version of the package.
If the vendoring experiment is enabled (see 'go help gopath'),
then when go get checks out or updates a Git repository,
it also updates any git submodules referenced by the repository.
For more about specifying packages, see 'go help packages'. For more about specifying packages, see 'go help packages'.
For more about how 'go get' finds source code to For more about how 'go get' finds source code to
@ -62,6 +69,7 @@ var getF = cmdGet.Flag.Bool("f", false, "")
var getT = cmdGet.Flag.Bool("t", false, "") var getT = cmdGet.Flag.Bool("t", false, "")
var getU = cmdGet.Flag.Bool("u", false, "") var getU = cmdGet.Flag.Bool("u", false, "")
var getFix = cmdGet.Flag.Bool("fix", false, "") var getFix = cmdGet.Flag.Bool("fix", false, "")
var getInsecure = cmdGet.Flag.Bool("insecure", false, "")
func init() { func init() {
addBuildFlags(cmdGet) addBuildFlags(cmdGet)
@ -73,10 +81,20 @@ func runGet(cmd *Command, args []string) {
fatalf("go get: cannot use -f flag without -u") fatalf("go get: cannot use -f flag without -u")
} }
// Disable any prompting for passwords by Git.
// Only has an effect for 2.3.0 or later, but avoiding
// the prompt in earlier versions is just too hard.
// See golang.org/issue/9341.
os.Setenv("GIT_TERMINAL_PROMPT", "0")
// Phase 1. Download/update. // Phase 1. Download/update.
var stk importStack var stk importStack
mode := 0
if *getT {
mode |= getTestDeps
}
for _, arg := range downloadPaths(args) { for _, arg := range downloadPaths(args) {
download(arg, &stk, *getT) download(arg, nil, &stk, mode)
} }
exitIfErrors() exitIfErrors()
@ -92,12 +110,13 @@ func runGet(cmd *Command, args []string) {
} }
args = importPaths(args) args = importPaths(args)
packagesForBuild(args)
// Phase 3. Install. // Phase 3. Install.
if *getD { if *getD {
// Download only. // Download only.
// Check delayed until now so that importPaths // Check delayed until now so that importPaths
// has a chance to print errors. // and packagesForBuild have a chance to print errors.
return return
} }
@ -148,13 +167,30 @@ var downloadRootCache = map[string]bool{}
// download runs the download half of the get command // download runs the download half of the get command
// for the package named by the argument. // for the package named by the argument.
func download(arg string, stk *importStack, getTestDeps bool) { func download(arg string, parent *Package, stk *importStack, mode int) {
p := loadPackage(arg, stk) load := func(path string, mode int) *Package {
if parent == nil {
return loadPackage(path, stk)
}
return loadImport(path, parent.Dir, parent, stk, nil, mode)
}
p := load(arg, mode)
if p.Error != nil && p.Error.hard { if p.Error != nil && p.Error.hard {
errorf("%s", p.Error) errorf("%s", p.Error)
return return
} }
// loadPackage inferred the canonical ImportPath from arg.
// Use that in the following to prevent hysteresis effects
// in e.g. downloadCache and packageCache.
// This allows invocations such as:
// mkdir -p $GOPATH/src/github.com/user
// cd $GOPATH/src/github.com/user
// go get ./foo
// see: golang.org/issue/9767
arg = p.ImportPath
// There's nothing to do if this is a package in the standard library. // There's nothing to do if this is a package in the standard library.
if p.Standard { if p.Standard {
return return
@ -163,7 +199,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// Only process each package once. // Only process each package once.
// (Unless we're fetching test dependencies for this package, // (Unless we're fetching test dependencies for this package,
// in which case we want to process it again.) // in which case we want to process it again.)
if downloadCache[arg] && !getTestDeps { if downloadCache[arg] && mode&getTestDeps == 0 {
return return
} }
downloadCache[arg] = true downloadCache[arg] = true
@ -175,7 +211,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// Download if the package is missing, or update if we're using -u. // Download if the package is missing, or update if we're using -u.
if p.Dir == "" || *getU { if p.Dir == "" || *getU {
// The actual download. // The actual download.
stk.push(p.ImportPath) stk.push(arg)
err := downloadPackage(p) err := downloadPackage(p)
if err != nil { if err != nil {
errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()}) errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
@ -183,6 +219,17 @@ func download(arg string, stk *importStack, getTestDeps bool) {
return return
} }
// Warn that code.google.com is shutting down. We
// issue the warning here because this is where we
// have the import stack.
if strings.HasPrefix(p.ImportPath, "code.google.com") {
fmt.Fprintf(os.Stderr, "warning: code.google.com is shutting down; import path %v will stop working\n", p.ImportPath)
if len(*stk) > 1 {
fmt.Fprintf(os.Stderr, "warning: package %v\n", strings.Join(*stk, "\n\timports "))
}
}
stk.pop()
args := []string{arg} args := []string{arg}
// If the argument has a wildcard in it, re-evaluate the wildcard. // If the argument has a wildcard in it, re-evaluate the wildcard.
// We delay this until after reloadPackage so that the old entry // We delay this until after reloadPackage so that the old entry
@ -208,9 +255,10 @@ func download(arg string, stk *importStack, getTestDeps bool) {
pkgs = pkgs[:0] pkgs = pkgs[:0]
for _, arg := range args { for _, arg := range args {
stk.push(arg) // Note: load calls loadPackage or loadImport,
p := loadPackage(arg, stk) // which push arg onto stk already.
stk.pop() // Do not push here too, or else stk will say arg imports arg.
p := load(arg, mode)
if p.Error != nil { if p.Error != nil {
errorf("%s", p.Error) errorf("%s", p.Error)
continue continue
@ -223,7 +271,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// due to wildcard expansion. // due to wildcard expansion.
for _, p := range pkgs { for _, p := range pkgs {
if *getFix { if *getFix {
run(stringList(tool("fix"), relPaths(p.allgofiles))) run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
// The imports might have changed, so reload again. // The imports might have changed, so reload again.
p = reloadPackage(arg, stk) p = reloadPackage(arg, stk)
@ -240,18 +288,31 @@ func download(arg string, stk *importStack, getTestDeps bool) {
} }
// Process dependencies, now that we know what they are. // Process dependencies, now that we know what they are.
for _, dep := range p.deps { for _, path := range p.Imports {
// Don't get test dependencies recursively. if path == "C" {
download(dep.ImportPath, stk, false) continue
} }
if getTestDeps { // Don't get test dependencies recursively.
// Imports is already vendor-expanded.
download(path, p, stk, 0)
}
if mode&getTestDeps != 0 {
// Process test dependencies when -t is specified. // Process test dependencies when -t is specified.
// (Don't get test dependencies for test dependencies.) // (Don't get test dependencies for test dependencies.)
// We pass useVendor here because p.load does not
// vendor-expand TestImports and XTestImports.
// The call to loadImport inside download needs to do that.
for _, path := range p.TestImports { for _, path := range p.TestImports {
download(path, stk, false) if path == "C" {
continue
}
download(path, p, stk, useVendor)
} }
for _, path := range p.XTestImports { for _, path := range p.XTestImports {
download(path, stk, false) if path == "C" {
continue
}
download(path, p, stk, useVendor)
} }
} }
@ -269,6 +330,12 @@ func downloadPackage(p *Package) error {
repo, rootPath string repo, rootPath string
err error err error
) )
security := secure
if *getInsecure {
security = insecure
}
if p.build.SrcRoot != "" { if p.build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src. // Directory exists. Look for checkout along path to src.
vcs, rootPath, err = vcsForDir(p) vcs, rootPath, err = vcsForDir(p)
@ -278,10 +345,15 @@ func downloadPackage(p *Package) error {
repo = "<local>" // should be unused; make distinctive repo = "<local>" // should be unused; make distinctive
// Double-check where it came from. // Double-check where it came from.
if *getU && vcs.remoteRepo != nil && !*getF { if *getU && vcs.remoteRepo != nil {
dir := filepath.Join(p.build.SrcRoot, rootPath) dir := filepath.Join(p.build.SrcRoot, rootPath)
if remote, err := vcs.remoteRepo(vcs, dir); err == nil { remote, err := vcs.remoteRepo(vcs, dir)
if rr, err := repoRootForImportPath(p.ImportPath); err == nil { if err != nil {
return err
}
repo = remote
if !*getF {
if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil {
repo := rr.repo repo := rr.repo
if rr.vcs.resolveRepo != nil { if rr.vcs.resolveRepo != nil {
resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo) resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
@ -289,7 +361,7 @@ func downloadPackage(p *Package) error {
repo = resolved repo = resolved
} }
} }
if remote != repo { if remote != repo && p.ImportComment != "" {
return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote) return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
} }
} }
@ -298,12 +370,15 @@ func downloadPackage(p *Package) error {
} else { } else {
// Analyze the import path to determine the version control system, // Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository. // repository, and the import path for the root of the repository.
rr, err := repoRootForImportPath(p.ImportPath) rr, err := repoRootForImportPath(p.ImportPath, security)
if err != nil { if err != nil {
return err return err
} }
vcs, repo, rootPath = rr.vcs, rr.repo, rr.root vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
} }
if !vcs.isSecure(repo) && !*getInsecure {
return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
}
if p.build.SrcRoot == "" { if p.build.SrcRoot == "" {
// Package not found. Put in first directory of $GOPATH. // Package not found. Put in first directory of $GOPATH.

2389
libgo/go/cmd/go/go_test.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@ environment variable (see 'go help gopath').
If no import paths are given, the action applies to the If no import paths are given, the action applies to the
package in the current directory. package in the current directory.
There are three reserved names for paths that should not be used There are four reserved names for paths that should not be used
for packages to be built with the go tool: for packages to be built with the go tool:
- "main" denotes the top-level package in a stand-alone executable. - "main" denotes the top-level package in a stand-alone executable.
@ -59,6 +59,9 @@ system.
- "std" is like all but expands to just the packages in the standard - "std" is like all but expands to just the packages in the standard
Go library. Go library.
- "cmd" expands to the Go repository's commands and their
internal libraries.
An import path is a pattern if it includes one or more "..." wildcards, An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and each of which can match any string, including the empty string and
strings containing slashes. Such a pattern expands to all package strings containing slashes. Such a pattern expands to all package
@ -74,7 +77,7 @@ By convention, this is arranged by starting each path with a
unique prefix that belongs to you. For example, paths used unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code, denoting remote repositories begin with the path to the code,
such as 'code.google.com/p/project'. such as 'github.com/user/repo'.
As a special case, if the package list is a list of .go files from a As a special case, if the package list is a list of .go files from a
single directory, the command is applied to a single synthesized single directory, the command is applied to a single synthesized
@ -192,7 +195,7 @@ example.org/repo or repo.git.
When a version control system supports multiple protocols, When a version control system supports multiple protocols,
each is tried in turn when downloading. For example, a Git each is tried in turn when downloading. For example, a Git
download tries git://, then https://, then http://. download tries https://, then git+ssh://.
If the import path is not a known code hosting site and also lacks a If the import path is not a known code hosting site and also lacks a
version control qualifier, the go tool attempts to fetch the import version control qualifier, the go tool attempts to fetch the import
@ -208,6 +211,10 @@ root. It must be a prefix or an exact match of the package being
fetched with "go get". If it's not an exact match, another http fetched with "go get". If it's not an exact match, another http
request is made at the prefix to verify the <meta> tags match. request is made at the prefix to verify the <meta> tags match.
The meta tag should appear as early in the file as possible.
In particular, it should appear before any raw JavaScript or CSS,
to avoid confusing the go command's restricted parser.
The vcs is one of "git", "hg", "svn", etc, The vcs is one of "git", "hg", "svn", etc,
The repo-root is the root of the version control system The repo-root is the root of the version control system
@ -217,10 +224,10 @@ For example,
import "example.org/pkg/foo" import "example.org/pkg/foo"
will result in the following request(s): will result in the following requests:
https://example.org/pkg/foo?go-get=1 (preferred) https://example.org/pkg/foo?go-get=1 (preferred)
http://example.org/pkg/foo?go-get=1 (fallback) http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure)
If that page contains the meta tag If that page contains the meta tag
@ -254,6 +261,11 @@ unless it is being referred to by that import path. In this way, import comments
let package authors make sure the custom import path is used and not a let package authors make sure the custom import path is used and not a
direct path to the underlying code hosting site. direct path to the underlying code hosting site.
If the vendoring experiment is enabled (see 'go help gopath'),
then import path checking is disabled for code found within vendor trees.
This makes it possible to copy code into alternate locations in vendor trees
without needing to update import comments.
See https://golang.org/s/go14customimport for details. See https://golang.org/s/go14customimport for details.
`, `,
} }
@ -275,10 +287,10 @@ standard Go tree.
Each directory listed in GOPATH must have a prescribed structure: Each directory listed in GOPATH must have a prescribed structure:
The src/ directory holds source code. The path below 'src' The src directory holds source code. The path below src
determines the import path or executable name. determines the import path or executable name.
The pkg/ directory holds installed package objects. The pkg directory holds installed package objects.
As in the Go tree, each target operating system and As in the Go tree, each target operating system and
architecture pair has its own subdirectory of pkg architecture pair has its own subdirectory of pkg
(pkg/GOOS_GOARCH). (pkg/GOOS_GOARCH).
@ -287,11 +299,11 @@ If DIR is a directory listed in the GOPATH, a package with
source in DIR/src/foo/bar can be imported as "foo/bar" and source in DIR/src/foo/bar can be imported as "foo/bar" and
has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin/ directory holds compiled commands. The bin directory holds compiled commands.
Each command is named for its source directory, but only Each command is named for its source directory, but only
the final element, not the entire path. That is, the the final element, not the entire path. That is, the
command with source in DIR/src/foo/quux is installed into command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
so that you can add DIR/bin to your PATH to get at the so that you can add DIR/bin to your PATH to get at the
installed commands. If the GOBIN environment variable is installed commands. If the GOBIN environment variable is
set, commands are installed to the directory it names instead set, commands are installed to the directory it names instead
@ -318,6 +330,168 @@ Here's an example directory layout:
Go searches each directory listed in GOPATH to find source code, Go searches each directory listed in GOPATH to find source code,
but new packages are always downloaded into the first directory but new packages are always downloaded into the first directory
in the list. in the list.
See https://golang.org/doc/code.html for an example.
Internal Directories
Code in or below a directory named "internal" is importable only
by code in the directory tree rooted at the parent of "internal".
Here's an extended version of the directory layout above:
/home/user/gocode/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
internal/
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The code in z.go is imported as "foo/internal/baz", but that
import statement can only appear in source files in the subtree
rooted at foo. The source files foo/f.go, foo/bar/x.go, and
foo/quux/y.go can all import "foo/internal/baz", but the source file
crash/bang/b.go cannot.
See https://golang.org/s/go14internal for details.
Vendor Directories
Go 1.5 includes experimental support for using local copies
of external dependencies to satisfy imports of those dependencies,
often referred to as vendoring. Setting the environment variable
GO15VENDOREXPERIMENT=1 enables that experimental support.
When the vendor experiment is enabled,
code below a directory named "vendor" is importable only
by code in the directory tree rooted at the parent of "vendor",
and only using an import path that omits the prefix up to and
including the vendor element.
Here's the example from the previous section,
but with the "internal" directory renamed to "vendor"
and a new foo/vendor/crash/bang directory added:
/home/user/gocode/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
vendor/
crash/
bang/ (go code in package bang)
b.go
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The same visibility rules apply as for internal, but the code
in z.go is imported as "baz", not as "foo/vendor/baz".
Code in vendor directories deeper in the source tree shadows
code in higher directories. Within the subtree rooted at foo, an import
of "crash/bang" resolves to "foo/vendor/crash/bang", not the
top-level "crash/bang".
Code in vendor directories is not subject to import path
checking (see 'go help importpath').
When the vendor experiment is enabled, 'go get' checks out
submodules when checking out or updating a git repository
(see 'go help get').
The vendoring semantics are an experiment, and they may change
in future releases. Once settled, they will be on by default.
See https://golang.org/s/go15vendor for details.
`,
}
var helpEnvironment = &Command{
UsageLine: "environment",
Short: "environment variables",
Long: `
The go command, and the tools it invokes, examine a few different
environment variables. For many of these, you can see the default
value of on your system by running 'go env NAME', where NAME is the
name of the variable.
General-purpose environment variables:
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOOS
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
GOPATH
See 'go help gopath'.
GORACE
Options for the race detector.
See https://golang.org/doc/articles/race_detector.html.
GOROOT
The root of the go tree.
Environment variables for use with cgo:
CC
The command to use to compile C code.
CGO_ENABLED
Whether the cgo command is supported. Either 0 or 1.
CGO_CFLAGS
Flags that cgo will pass to the compiler when compiling
C code.
CGO_CPPFLAGS
Flags that cgo will pass to the compiler when compiling
C or C++ code.
CGO_CXXFLAGS
Flags that cgo will pass to the compiler when compiling
C++ code.
CGO_LDFLAGS
Flags that cgo will pass to the compiler when linking.
CXX
The command to use to compile C++ code.
Architecture-specific environment variables:
GOARM
For GOARCH=arm, the ARM architecture for which to compile.
Valid values are 5, 6, 7.
GO386
For GOARCH=386, the floating point instruction set.
Valid values are 387, sse2.
Special-purpose environment variables:
GOROOT_FINAL
The root of the installed Go tree, when it is
installed in a location other than where it is built.
File names in stack traces are rewritten from GOROOT to
GOROOT_FINAL.
GO15VENDOREXPERIMENT
Set to 1 to enable the Go 1.5 vendoring experiment.
GO_EXTLINK_ENABLED
Whether the linker should use external linking mode
when using -linkmode=auto with code that uses cgo.
Set to 0 to disable external linking mode, 1 to enable it.
`, `,
} }
@ -333,10 +507,9 @@ the extension of the file name. These extensions are:
Go source files. Go source files.
.c, .h .c, .h
C source files. C source files.
If the package uses cgo, these will be compiled with the If the package uses cgo or SWIG, these will be compiled with the
OS-native compiler (typically gcc); otherwise they will be OS-native compiler (typically gcc); otherwise they will
compiled with the Go-specific support compiler, trigger an error.
5c, 6c, or 8c, etc. as appropriate.
.cc, .cpp, .cxx, .hh, .hpp, .hxx .cc, .cpp, .cxx, .hh, .hpp, .hxx
C++ source files. Only useful with cgo or SWIG, and always C++ source files. Only useful with cgo or SWIG, and always
compiled with the OS-native compiler. compiled with the OS-native compiler.
@ -345,10 +518,9 @@ the extension of the file name. These extensions are:
compiled with the OS-native compiler. compiled with the OS-native compiler.
.s, .S .s, .S
Assembler source files. Assembler source files.
If the package uses cgo, these will be assembled with the If the package uses cgo or SWIG, these will be assembled with the
OS-native assembler (typically gcc (sic)); otherwise they OS-native assembler (typically gcc (sic)); otherwise they
will be assembled with the Go-specific support assembler, will be assembled with the Go assembler.
5a, 6a, or 8a, etc., as appropriate.
.swig, .swigcxx .swig, .swigcxx
SWIG definition files. SWIG definition files.
.syso .syso
@ -360,3 +532,43 @@ at the first item in the file that is not a blank line or //-style
line comment. line comment.
`, `,
} }
var helpBuildmode = &Command{
UsageLine: "buildmode",
Short: "description of build modes",
Long: `
The 'go build' and 'go install' commands take a -buildmode argument which
indicates which kind of object file is to be built. Currently supported values
are:
-buildmode=archive
Build the listed non-main packages into .a files. Packages named
main are ignored.
-buildmode=c-archive
Build the listed main package, plus all packages it imports,
into a C archive file. The only callable symbols will be those
functions exported using a cgo //export comment. Requires
exactly one main package to be listed.
-buildmode=c-shared
Build the listed main packages, plus all packages that they
import, into C shared libraries. The only callable symbols will
be those functions exported using a cgo //export comment.
Non-main packages are ignored.
-buildmode=default
Listed main packages are built into executables and listed
non-main packages are built into .a files (the default
behavior).
-buildmode=shared
Combine all the listed non-main packages into a single shared
library that will be used when building with the -linkshared
option. Packages named main are ignored.
-buildmode=exe
Build the listed main packages and everything they import into
executables. Packages not named main are ignored.
`,
}

View File

@ -18,11 +18,25 @@ import (
"log" "log"
"net/http" "net/http"
"net/url" "net/url"
"time"
) )
// httpClient is the default HTTP client, but a variable so it can be // httpClient is the default HTTP client, but a variable so it can be
// changed by tests, without modifying http.DefaultClient. // changed by tests, without modifying http.DefaultClient.
var httpClient = http.DefaultClient var httpClient = http.DefaultClient
var impatientHTTPClient = &http.Client{
Timeout: time.Duration(5 * time.Second),
}
type httpError struct {
status string
statusCode int
url string
}
func (e *httpError) Error() string {
return fmt.Sprintf("%s: %s", e.url, e.status)
}
// httpGET returns the data from an HTTP GET request for the given URL. // httpGET returns the data from an HTTP GET request for the given URL.
func httpGET(url string) ([]byte, error) { func httpGET(url string) ([]byte, error) {
@ -32,7 +46,9 @@ func httpGET(url string) ([]byte, error) {
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != 200 { if resp.StatusCode != 200 {
return nil, fmt.Errorf("%s: %s", url, resp.Status) err := &httpError{status: resp.Status, statusCode: resp.StatusCode, url: url}
return nil, err
} }
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
@ -43,7 +59,7 @@ func httpGET(url string) ([]byte, error) {
// httpsOrHTTP returns the body of either the importPath's // httpsOrHTTP returns the body of either the importPath's
// https resource or, if unavailable, the http resource. // https resource or, if unavailable, the http resource.
func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) { func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body io.ReadCloser, err error) {
fetch := func(scheme string) (urlStr string, res *http.Response, err error) { fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
u, err := url.Parse(scheme + "://" + importPath) u, err := url.Parse(scheme + "://" + importPath)
if err != nil { if err != nil {
@ -54,7 +70,11 @@ func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err erro
if buildV { if buildV {
log.Printf("Fetching %s", urlStr) log.Printf("Fetching %s", urlStr)
} }
if security == insecure && scheme == "https" { // fail earlier
res, err = impatientHTTPClient.Get(urlStr)
} else {
res, err = httpClient.Get(urlStr) res, err = httpClient.Get(urlStr)
}
return return
} }
closeBody := func(res *http.Response) { closeBody := func(res *http.Response) {
@ -72,8 +92,10 @@ func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err erro
} }
} }
closeBody(res) closeBody(res)
if security == insecure {
urlStr, res, err = fetch("http") urlStr, res, err = fetch("http")
} }
}
if err != nil { if err != nil {
closeBody(res) closeBody(res)
return "", nil, err return "", nil, err

View File

@ -21,9 +21,10 @@ List lists the packages named by the import paths, one per line.
The default output shows the package import path: The default output shows the package import path:
code.google.com/p/google-api-go-client/books/v1 bytes
code.google.com/p/goauth2/oauth encoding/json
code.google.com/p/sqlite github.com/gorilla/mux
golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the The -f flag specifies an alternate format for the list, using the
syntax of package template. The default output is equivalent to -f syntax of package template. The default output is equivalent to -f
@ -36,6 +37,7 @@ syntax of package template. The default output is equivalent to -f
Name string // package name Name string // package name
Doc string // package documentation string Doc string // package documentation string
Target string // install path Target string // install path
Shlib string // the shared library that contains this package (only set when -linkshared)
Goroot bool // is this package in the Go root? Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library? Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package? Stale bool // would 'go install' do anything for this package?
@ -126,6 +128,7 @@ var listJson = cmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'} var nl = []byte{'\n'}
func runList(cmd *Command, args []string) { func runList(cmd *Command, args []string) {
buildModeInit()
out := newTrackingWriter(os.Stdout) out := newTrackingWriter(os.Stdout)
defer out.w.Flush() defer out.w.Flush()
@ -173,6 +176,10 @@ func runList(cmd *Command, args []string) {
} }
for _, pkg := range load(args) { for _, pkg := range load(args) {
// Show vendor-expanded paths in listing
pkg.TestImports = pkg.vendored(pkg.TestImports)
pkg.XTestImports = pkg.vendored(pkg.XTestImports)
do(pkg) do(pkg)
} }
} }

View File

@ -5,6 +5,7 @@
package main package main
import ( import (
"bufio"
"bytes" "bytes"
"flag" "flag"
"fmt" "fmt"
@ -76,6 +77,7 @@ func (c *Command) Runnable() bool {
var commands = []*Command{ var commands = []*Command{
cmdBuild, cmdBuild,
cmdClean, cmdClean,
cmdDoc,
cmdEnv, cmdEnv,
cmdFix, cmdFix,
cmdFmt, cmdFmt,
@ -90,8 +92,10 @@ var commands = []*Command{
cmdVet, cmdVet,
helpC, helpC,
helpBuildmode,
helpFileType, helpFileType,
helpGopath, helpGopath,
helpEnvironment,
helpImportPath, helpImportPath,
helpPackages, helpPackages,
helpTestflag, helpTestflag,
@ -109,6 +113,8 @@ func setExitStatus(n int) {
exitMu.Unlock() exitMu.Unlock()
} }
var origEnv []string
func main() { func main() {
_ = go11tag _ = go11tag
flag.Usage = usage flag.Usage = usage
@ -139,7 +145,7 @@ func main() {
fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p) fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
os.Exit(2) os.Exit(2)
} }
if build.IsLocalImport(p) { if !filepath.IsAbs(p) {
fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p) fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p)
os.Exit(2) os.Exit(2)
} }
@ -151,8 +157,20 @@ func main() {
os.Exit(2) os.Exit(2)
} }
// Set environment (GOOS, GOARCH, etc) explicitly.
// In theory all the commands we invoke should have
// the same default computation of these as we do,
// but in practice there might be skew
// This makes sure we all agree.
origEnv = os.Environ()
for _, env := range mkEnv() {
if os.Getenv(env.name) != env.value {
os.Setenv(env.name, env.value)
}
}
for _, cmd := range commands { for _, cmd := range commands {
if cmd.Name() == args[0] && cmd.Run != nil { if cmd.Name() == args[0] && cmd.Runnable() {
cmd.Flag.Usage = func() { cmd.Usage() } cmd.Flag.Usage = func() { cmd.Usage() }
if cmd.CustomFlags { if cmd.CustomFlags {
args = args[1:] args = args[1:]
@ -200,8 +218,8 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. // DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.
// Edit the documentation in other files and rerun mkdoc.sh to generate this one. // Edit the documentation in other files and rerun mkalldocs.sh to generate this one.
/* /*
{{range .}}{{if .Short}}{{.Short | capitalize}} {{range .}}{{if .Short}}{{.Short | capitalize}}
@ -217,12 +235,35 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
package main package main
` `
// An errWriter wraps a writer, recording whether a write error occurred.
type errWriter struct {
w io.Writer
err error
}
func (w *errWriter) Write(b []byte) (int, error) {
n, err := w.w.Write(b)
if err != nil {
w.err = err
}
return n, err
}
// tmpl executes the given template text on data, writing the result to w. // tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) { func tmpl(w io.Writer, text string, data interface{}) {
t := template.New("top") t := template.New("top")
t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize}) t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
template.Must(t.Parse(text)) template.Must(t.Parse(text))
if err := t.Execute(w, data); err != nil { ew := &errWriter{w: w}
err := t.Execute(ew, data)
if ew.err != nil {
// I/O error writing. Ignore write on closed pipe.
if strings.Contains(ew.err.Error(), "pipe") {
os.Exit(1)
}
fatalf("writing output: %v", ew.err)
}
if err != nil {
panic(err) panic(err)
} }
} }
@ -236,13 +277,17 @@ func capitalize(s string) string {
} }
func printUsage(w io.Writer) { func printUsage(w io.Writer) {
tmpl(w, usageTemplate, commands) bw := bufio.NewWriter(w)
tmpl(bw, usageTemplate, commands)
bw.Flush()
} }
func usage() { func usage() {
// special case "go test -h" // special case "go test -h"
if len(os.Args) > 1 && os.Args[1] == "test" { if len(os.Args) > 1 && os.Args[1] == "test" {
help([]string{"testflag"}) os.Stdout.WriteString(testUsage + "\n\n" +
strings.TrimSpace(testFlag1) + "\n\n" +
strings.TrimSpace(testFlag2) + "\n")
os.Exit(2) os.Exit(2)
} }
printUsage(os.Stderr) printUsage(os.Stderr)
@ -308,7 +353,7 @@ func importPathsNoDotExpansion(args []string) []string {
} else { } else {
a = path.Clean(a) a = path.Clean(a)
} }
if a == "all" || a == "std" { if a == "all" || a == "std" || a == "cmd" {
out = append(out, allPackages(a)...) out = append(out, allPackages(a)...)
continue continue
} }
@ -401,11 +446,10 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
// The environment is the current process's environment // The environment is the current process's environment
// but with an updated $PWD, so that an os.Getwd in the // but with an updated $PWD, so that an os.Getwd in the
// child will be faster. // child will be faster.
func envForDir(dir string) []string { func envForDir(dir string, base []string) []string {
env := os.Environ()
// Internally we only use rooted paths, so dir is rooted. // Internally we only use rooted paths, so dir is rooted.
// Even if dir is not rooted, no harm done. // Even if dir is not rooted, no harm done.
return mergeEnvLists([]string{"PWD=" + dir}, env) return mergeEnvLists([]string{"PWD=" + dir}, base)
} }
// mergeEnvLists merges the two environment lists such that // mergeEnvLists merges the two environment lists such that
@ -458,6 +502,28 @@ func hasPathPrefix(s, prefix string) bool {
} }
} }
// hasFilePathPrefix reports whether the filesystem path s begins with the
// elements in prefix.
func hasFilePathPrefix(s, prefix string) bool {
sv := strings.ToUpper(filepath.VolumeName(s))
pv := strings.ToUpper(filepath.VolumeName(prefix))
s = s[len(sv):]
prefix = prefix[len(pv):]
switch {
default:
return false
case sv != pv:
return false
case len(s) == len(prefix):
return s == prefix
case len(s) > len(prefix):
if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
return strings.HasPrefix(s, prefix)
}
return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
}
}
// treeCanMatchPattern(pattern)(name) reports whether // treeCanMatchPattern(pattern)(name) reports whether
// name or children of name can possibly match pattern. // name or children of name can possibly match pattern.
// Pattern is the same limited glob accepted by matchPattern. // Pattern is the same limited glob accepted by matchPattern.
@ -475,8 +541,8 @@ func treeCanMatchPattern(pattern string) func(name string) bool {
// allPackages returns all the packages that can be found // allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern. // under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages) // The pattern is either "all" (all packages), "std" (standard packages),
// or a path including "...". // "cmd" (standard commands), or a path including "...".
func allPackages(pattern string) []string { func allPackages(pattern string) []string {
pkgs := matchPackages(pattern) pkgs := matchPackages(pattern)
if len(pkgs) == 0 { if len(pkgs) == 0 {
@ -488,7 +554,7 @@ func allPackages(pattern string) []string {
func matchPackages(pattern string) []string { func matchPackages(pattern string) []string {
match := func(string) bool { return true } match := func(string) bool { return true }
treeCanMatch := func(string) bool { return true } treeCanMatch := func(string) bool { return true }
if pattern != "all" && pattern != "std" { if pattern != "all" && pattern != "std" && pattern != "cmd" {
match = matchPattern(pattern) match = matchPattern(pattern)
treeCanMatch = treeCanMatchPattern(pattern) treeCanMatch = treeCanMatchPattern(pattern)
} }
@ -501,47 +567,16 @@ func matchPackages(pattern string) []string {
} }
var pkgs []string var pkgs []string
// Commands
cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == cmd {
return nil
}
name := path[len(cmd):]
if !treeCanMatch(name) {
return filepath.SkipDir
}
// Commands are all in cmd/, not in subdirectories.
if strings.Contains(name, string(filepath.Separator)) {
return filepath.SkipDir
}
// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
name = "cmd/" + name
if have[name] {
return nil
}
have[name] = true
if !match(name) {
return nil
}
_, err = buildContext.ImportDir(path, 0)
if err != nil {
if _, noGo := err.(*build.NoGoError); !noGo {
log.Print(err)
}
return nil
}
pkgs = append(pkgs, name)
return nil
})
for _, src := range buildContext.SrcDirs() { for _, src := range buildContext.SrcDirs() {
if pattern == "std" && src != gorootSrc { if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
continue continue
} }
src = filepath.Clean(src) + string(filepath.Separator) src = filepath.Clean(src) + string(filepath.Separator)
filepath.Walk(src, func(path string, fi os.FileInfo, err error) error { root := src
if pattern == "cmd" {
root += "cmd" + string(filepath.Separator)
}
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == src { if err != nil || !fi.IsDir() || path == src {
return nil return nil
} }
@ -553,7 +588,10 @@ func matchPackages(pattern string) []string {
} }
name := filepath.ToSlash(path[len(src):]) name := filepath.ToSlash(path[len(src):])
if pattern == "std" && strings.Contains(name, ".") { if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
// The name "std" is only the standard library.
// If the name has a dot, assume it's a domain name for go get,
// and if the name is cmd, it's the root of the command tree.
return filepath.SkipDir return filepath.SkipDir
} }
if !treeCanMatch(name) { if !treeCanMatch(name) {
@ -659,7 +697,7 @@ func stringList(args ...interface{}) []string {
case string: case string:
x = append(x, arg) x = append(x, arg)
default: default:
panic("stringList: invalid argument") panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
} }
} }
return x return x

116
libgo/go/cmd/go/note.go Normal file
View File

@ -0,0 +1,116 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"os"
)
func readAligned4(r io.Reader, sz int32) ([]byte, error) {
full := (sz + 3) &^ 3
data := make([]byte, full)
_, err := io.ReadFull(r, data)
if err != nil {
return nil, err
}
data = data[:sz]
return data, nil
}
func readELFNote(filename, name string, typ int32) ([]byte, error) {
f, err := elf.Open(filename)
if err != nil {
return nil, err
}
for _, sect := range f.Sections {
if sect.Type != elf.SHT_NOTE {
continue
}
r := sect.Open()
for {
var namesize, descsize, noteType int32
err = binary.Read(r, f.ByteOrder, &namesize)
if err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("read namesize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, &descsize)
if err != nil {
return nil, fmt.Errorf("read descsize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, &noteType)
if err != nil {
return nil, fmt.Errorf("read type failed: %v", err)
}
noteName, err := readAligned4(r, namesize)
if err != nil {
return nil, fmt.Errorf("read name failed: %v", err)
}
desc, err := readAligned4(r, descsize)
if err != nil {
return nil, fmt.Errorf("read desc failed: %v", err)
}
if name == string(noteName) && typ == noteType {
return desc, nil
}
}
}
return nil, nil
}
var elfGoNote = []byte("Go\x00\x00")
// readELFGoBuildID the Go build ID string from an ELF binary.
// The Go build ID is stored in a note described by an ELF PT_NOTE prog header.
// The caller has already opened filename, to get f, and read the first 4 kB out, in data.
func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) {
// Assume the note content is in the first 4 kB, already read.
// Rewrite the ELF header to set shnum to 0, so that we can pass
// the data to elf.NewFile and it will decode the Prog list but not
// try to read the section headers and the string table from disk.
// That's a waste of I/O when all we care about is the Prog list
// and the one ELF note.
switch elf.Class(data[elf.EI_CLASS]) {
case elf.ELFCLASS32:
data[48] = 0
data[49] = 0
case elf.ELFCLASS64:
data[60] = 0
data[61] = 0
}
const elfGoBuildIDTag = 4
ef, err := elf.NewFile(bytes.NewReader(data))
if err != nil {
return "", &os.PathError{Path: filename, Op: "parse", Err: err}
}
for _, p := range ef.Progs {
if p.Type != elf.PT_NOTE || p.Off >= uint64(len(data)) || p.Off+p.Filesz >= uint64(len(data)) || p.Filesz < 16 {
continue
}
note := data[p.Off : p.Off+p.Filesz]
nameSize := ef.ByteOrder.Uint32(note)
valSize := ef.ByteOrder.Uint32(note[4:])
tag := ef.ByteOrder.Uint32(note[8:])
name := note[12:16]
if nameSize != 4 || 16+valSize > uint32(len(note)) || tag != elfGoBuildIDTag || !bytes.Equal(name, elfGoNote) {
continue
}
return string(note[16 : 16+valSize]), nil
}
// No note. Treat as successful but build ID empty.
return "", nil
}

View File

@ -0,0 +1,49 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main_test
import (
main "cmd/go"
"runtime"
"testing"
)
func TestNoteReading(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`)
const buildID = "TestNoteReading-Build-ID"
tg.run("build", "-ldflags", "-buildid="+buildID, "-o", tg.path("hello.exe"), tg.path("hello.go"))
id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary: %v", err)
}
if id != buildID {
t.Fatalf("buildID in hello binary = %q, want %q", id, buildID)
}
if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
t.Skipf("skipping - golang.org/issue/11184")
}
switch runtime.GOOS {
case "plan9":
// no external linking
t.Logf("no external linking - skipping linkmode=external test")
case "solaris":
t.Logf("skipping - golang.org/issue/12178")
default:
tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
}
if id != buildID {
t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,8 @@ Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix. A Go source file is defined to be a file ending in a literal ".go" suffix.
By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'. If the -exec flag is given, 'go run' invokes the binary using xprog:
'xprog a.out arguments...'.
If the -exec flag is not given, GOOS or GOARCH is different from the system If the -exec flag is not given, GOOS or GOARCH is different from the system
default, and a program named go_$GOOS_$GOARCH_exec can be found default, and a program named go_$GOOS_$GOARCH_exec can be found
on the current search path, 'go run' invokes the binary using that program, on the current search path, 'go run' invokes the binary using that program,
@ -64,6 +65,7 @@ func printStderr(args ...interface{}) (int, error) {
func runRun(cmd *Command, args []string) { func runRun(cmd *Command, args []string) {
raceInit() raceInit()
buildModeInit()
var b builder var b builder
b.init() b.init()
b.print = printStderr b.print = printStderr
@ -136,6 +138,7 @@ func runStdin(cmdline []string) {
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
cmd.Env = origEnv
startSigHandlers() startSigHandlers()
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
errorf("%v", err) errorf("%v", err)

View File

@ -33,9 +33,11 @@ func init() {
cmdTest.Run = runTest cmdTest.Run = runTest
} }
const testUsage = "test [-c] [-i] [build and test flags] [packages] [flags for test binary]"
var cmdTest = &Command{ var cmdTest = &Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "test [-c] [-i] [build and test flags] [packages] [flags for test binary]", UsageLine: testUsage,
Short: "test packages", Short: "test packages",
Long: ` Long: `
'Go test' automates testing the packages named by the import paths. 'Go test' automates testing the packages named by the import paths.
@ -64,6 +66,21 @@ with source in the current directory, including tests, and runs the tests.
The package is built in a temporary directory so it does not interfere with the The package is built in a temporary directory so it does not interfere with the
non-test installation. non-test installation.
` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
`,
}
const testFlag1 = `
In addition to the build flags, the flags handled by 'go test' itself are: In addition to the build flags, the flags handled by 'go test' itself are:
-c -c
@ -83,21 +100,9 @@ In addition to the build flags, the flags handled by 'go test' itself are:
Compile the test binary to the named file. Compile the test binary to the named file.
The test still runs (unless -c or -i is specified). The test still runs (unless -c or -i is specified).
The test binary also accepts flags that control execution of the test; these The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'. See 'go help testflag' for details. flags are also accessible by 'go test'.
`
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
`,
}
var helpTestflag = &Command{ var helpTestflag = &Command{
UsageLine: "testflag", UsageLine: "testflag",
@ -107,13 +112,18 @@ The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary. and flags that apply to the resulting test binary.
Several of the flags control profiling and write an execution profile Several of the flags control profiling and write an execution profile
suitable for "go tool pprof"; run "go tool pprof help" for more suitable for "go tool pprof"; run "go tool pprof -h" for more
information. The --alloc_space, --alloc_objects, and --show_bytes information. The --alloc_space, --alloc_objects, and --show_bytes
options of pprof control how the information is presented. options of pprof control how the information is presented.
The following flags are recognized by the 'go test' command and The following flags are recognized by the 'go test' command and
control the execution of any test: control the execution of any test:
` + strings.TrimSpace(testFlag2) + `
`,
}
const testFlag2 = `
-bench regexp -bench regexp
Run benchmarks matching the regular expression. Run benchmarks matching the regular expression.
By default, no benchmarks run. To run all benchmarks, By default, no benchmarks run. To run all benchmarks,
@ -135,12 +145,17 @@ control the execution of any test:
-blockprofilerate n -blockprofilerate n
Control the detail provided in goroutine blocking profiles by Control the detail provided in goroutine blocking profiles by
calling runtime.SetBlockProfileRate with n. calling runtime.SetBlockProfileRate with n.
See 'godoc runtime SetBlockProfileRate'. See 'go doc runtime.SetBlockProfileRate'.
The profiler aims to sample, on average, one blocking event every The profiler aims to sample, on average, one blocking event every
n nanoseconds the program spends blocked. By default, n nanoseconds the program spends blocked. By default,
if -test.blockprofile is set without this flag, all blocking events if -test.blockprofile is set without this flag, all blocking events
are recorded, equivalent to -test.blockprofilerate=1. are recorded, equivalent to -test.blockprofilerate=1.
-count n
Run each test and benchmark n times (default 1).
If -cpu is set, run n times for each GOMAXPROCS value.
Examples are always run once.
-cover -cover
Enable coverage analysis. Enable coverage analysis.
@ -180,7 +195,7 @@ control the execution of any test:
-memprofilerate n -memprofilerate n
Enable more precise (and expensive) memory profiles by setting Enable more precise (and expensive) memory profiles by setting
runtime.MemProfileRate. See 'godoc runtime MemProfileRate'. runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
To profile all memory allocations, use -test.memprofilerate=1 To profile all memory allocations, use -test.memprofilerate=1
and pass --alloc_space flag to the pprof tool. and pass --alloc_space flag to the pprof tool.
@ -205,6 +220,11 @@ control the execution of any test:
-timeout t -timeout t
If a test runs longer than t, panic. If a test runs longer than t, panic.
The default is 10 minutes (10m).
-trace trace.out
Write an execution trace to the specified file before exiting.
Writes test binary as -c would.
-v -v
Verbose output: log all tests as they are run. Also print all Verbose output: log all tests as they are run. Also print all
@ -229,8 +249,7 @@ The test flags that generate profiles (other than for coverage) also
leave the test binary in pkg.test for use when analyzing the profiles. leave the test binary in pkg.test for use when analyzing the profiles.
Flags not recognized by 'go test' must be placed after any specified packages. Flags not recognized by 'go test' must be placed after any specified packages.
`, `
}
var helpTestfunc = &Command{ var helpTestfunc = &Command{
UsageLine: "testfunc", UsageLine: "testfunc",
@ -310,6 +329,7 @@ func runTest(cmd *Command, args []string) {
findExecCmd() // initialize cached result findExecCmd() // initialize cached result
raceInit() raceInit()
buildModeInit()
pkgs := packagesForBuild(pkgArgs) pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 { if len(pkgs) == 0 {
fatalf("no packages to test") fatalf("no packages to test")
@ -342,11 +362,11 @@ func runTest(cmd *Command, args []string) {
// been given on the command line (implicit current directory) // been given on the command line (implicit current directory)
// or when benchmarking. // or when benchmarking.
// Also stream if we're showing output anyway with a // Also stream if we're showing output anyway with a
// single package under test. In that case, streaming the // single package under test or if parallelism is set to 1.
// output produces the same result as not streaming, // In these cases, streaming the output produces the same result
// just more immediately. // as not streaming, just more immediately.
testStreamOutput = len(pkgArgs) == 0 || testBench || testStreamOutput = len(pkgArgs) == 0 || testBench ||
(len(pkgs) <= 1 && testShowPass) (testShowPass && (len(pkgs) == 1 || buildP == 1))
var b builder var b builder
b.init() b.init()
@ -364,10 +384,10 @@ func runTest(cmd *Command, args []string) {
for _, path := range p.Imports { for _, path := range p.Imports {
deps[path] = true deps[path] = true
} }
for _, path := range p.TestImports { for _, path := range p.vendored(p.TestImports) {
deps[path] = true deps[path] = true
} }
for _, path := range p.XTestImports { for _, path := range p.vendored(p.XTestImports) {
deps[path] = true deps[path] = true
} }
} }
@ -376,7 +396,7 @@ func runTest(cmd *Command, args []string) {
if deps["C"] { if deps["C"] {
delete(deps, "C") delete(deps, "C")
deps["runtime/cgo"] = true deps["runtime/cgo"] = true
if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH { if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
deps["cmd/cgo"] = true deps["cmd/cgo"] = true
} }
} }
@ -428,6 +448,10 @@ func runTest(cmd *Command, args []string) {
// Mark all the coverage packages for rebuilding with coverage. // Mark all the coverage packages for rebuilding with coverage.
for _, p := range testCoverPkgs { for _, p := range testCoverPkgs {
// There is nothing to cover in package unsafe; it comes from the compiler.
if p.ImportPath == "unsafe" {
continue
}
p.Stale = true // rebuild p.Stale = true // rebuild
p.fake = true // do not warn about rebuild p.fake = true // do not warn about rebuild
p.coverMode = testCoverMode p.coverMode = testCoverMode
@ -562,15 +586,20 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
var imports, ximports []*Package var imports, ximports []*Package
var stk importStack var stk importStack
stk.push(p.ImportPath + " (test)") stk.push(p.ImportPath + " (test)")
for _, path := range p.TestImports { for i, path := range p.TestImports {
p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path]) p1 := loadImport(path, p.Dir, p, &stk, p.build.TestImportPos[path], useVendor)
if !reqStdPkgSrc && p1.Standard { if !reqStdPkgSrc && p1.Standard {
continue continue
} }
if p1.Error != nil { if p1.Error != nil {
return nil, nil, nil, p1.Error return nil, nil, nil, p1.Error
} }
if contains(p1.Deps, p.ImportPath) { if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, nil, err
}
if contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
// Same error that loadPackage returns (via reusePackage) in pkg.go. // Same error that loadPackage returns (via reusePackage) in pkg.go.
// Can't change that code, because that code is only for loading the // Can't change that code, because that code is only for loading the
// non-test copy of a package. // non-test copy of a package.
@ -581,25 +610,32 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
} }
return nil, nil, nil, err return nil, nil, nil, err
} }
p.TestImports[i] = p1.ImportPath
imports = append(imports, p1) imports = append(imports, p1)
} }
stk.pop() stk.pop()
stk.push(p.ImportPath + "_test") stk.push(p.ImportPath + "_test")
pxtestNeedsPtest := false pxtestNeedsPtest := false
for _, path := range p.XTestImports { for i, path := range p.XTestImports {
if path == p.ImportPath { p1 := loadImport(path, p.Dir, p, &stk, p.build.XTestImportPos[path], useVendor)
pxtestNeedsPtest = true
continue
}
p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
if !reqStdPkgSrc && p1.Standard { if !reqStdPkgSrc && p1.Standard {
continue continue
} }
if p1.Error != nil { if p1.Error != nil {
return nil, nil, nil, p1.Error return nil, nil, nil, p1.Error
} }
if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, nil, err
}
if p1.ImportPath == p.ImportPath {
pxtestNeedsPtest = true
} else {
ximports = append(ximports, p1) ximports = append(ximports, p1)
} }
p.XTestImports[i] = p1.ImportPath
}
stk.pop() stk.pop()
// Use last element of import path, not package name. // Use last element of import path, not package name.
@ -723,7 +759,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if dep == ptest.ImportPath { if dep == ptest.ImportPath {
pmain.imports = append(pmain.imports, ptest) pmain.imports = append(pmain.imports, ptest)
} else { } else {
p1 := loadImport(dep, "", &stk, nil) p1 := loadImport(dep, "", nil, &stk, nil, 0)
if !reqStdPkgSrc && p1.Standard { if !reqStdPkgSrc && p1.Standard {
continue continue
} }
@ -781,6 +817,12 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
recompileForTest(pmain, p, ptest, testDir) recompileForTest(pmain, p, ptest, testDir)
} }
if buildContext.GOOS == "darwin" {
if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" {
t.NeedCgo = true
}
}
for _, cp := range pmain.imports { for _, cp := range pmain.imports {
if len(cp.coverVars) > 0 { if len(cp.coverVars) > 0 {
t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars}) t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
@ -997,7 +1039,7 @@ func (b *builder) runTest(a *action) error {
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.p.Dir cmd.Dir = a.p.Dir
cmd.Env = envForDir(cmd.Dir) cmd.Env = envForDir(cmd.Dir, origEnv)
var buf bytes.Buffer var buf bytes.Buffer
if testStreamOutput { if testStreamOutput {
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
@ -1216,6 +1258,7 @@ type testFuncs struct {
NeedTest bool NeedTest bool
ImportXtest bool ImportXtest bool
NeedXtest bool NeedXtest bool
NeedCgo bool
Cover []coverInfo Cover []coverInfo
} }
@ -1319,6 +1362,10 @@ import (
{{range $i, $p := .Cover}} {{range $i, $p := .Cover}}
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
{{end}} {{end}}
{{if .NeedCgo}}
_ "runtime/cgo"
{{end}}
) )
var tests = []testing.InternalTest{ var tests = []testing.InternalTest{

View File

@ -4,6 +4,6 @@
// Test go generate variable substitution. // Test go generate variable substitution.
//go:generate echo $GOARCH $GOFILE $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123 //go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123
package p package p

View File

@ -0,0 +1,10 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test -run flag
//go:generate echo oh yes my man
//go:generate echo no, no, a thousand times no
package p

View File

@ -0,0 +1 @@
package main

1
libgo/go/cmd/go/testdata/rundir/x.go vendored Normal file
View File

@ -0,0 +1 @@
package main

View File

@ -0,0 +1 @@
package q1

View File

@ -0,0 +1,6 @@
package q1
import "testing"
import _ "testcycle/q1"
func Test(t *testing.T) {}

View File

@ -0,0 +1 @@
package p1

View File

@ -0,0 +1,3 @@
package p1
import _ "testdep/p2"

View File

@ -0,0 +1,3 @@
package p2
import _ "testdep/p3"

View File

@ -0,0 +1,3 @@
// +build ignore
package ignored

View File

@ -0,0 +1,3 @@
package vend
import _ "r"

View File

@ -0,0 +1,3 @@
package vend
import _ "p"

View File

@ -0,0 +1,10 @@
package main
import (
"fmt"
"strings" // really ../vendor/strings
)
func main() {
fmt.Printf("%s\n", strings.Msg)
}

View File

@ -0,0 +1,12 @@
package main
import (
"strings" // really ../vendor/strings
"testing"
)
func TestMsgInternal(t *testing.T) {
if strings.Msg != "hello, world" {
t.Fatal("unexpected msg: %v", strings.Msg)
}
}

View File

@ -0,0 +1,12 @@
package main_test
import (
"strings" // really ../vendor/strings
"testing"
)
func TestMsgExternal(t *testing.T) {
if strings.Msg != "hello, world" {
t.Fatal("unexpected msg: %v", strings.Msg)
}
}

View File

@ -0,0 +1,3 @@
package subdir
import _ "r"

View File

@ -0,0 +1,3 @@
package subdir
import _ "p"

View File

@ -0,0 +1 @@
package p

View File

@ -0,0 +1 @@
package q

View File

@ -0,0 +1,3 @@
package strings
var Msg = "hello, world"

View File

@ -0,0 +1,3 @@
package invalid
import "vend/x/invalid/vendor/foo"

View File

@ -0,0 +1 @@
package p

View File

@ -0,0 +1,3 @@
package p
import _ "notfound"

View File

@ -0,0 +1 @@
package r

View File

@ -0,0 +1,5 @@
package x
import _ "p"
import _ "q"
import _ "r"

View File

@ -0,0 +1,9 @@
// +build tagtest
package p
import "fmt"
func g() {
fmt.Printf("%d", 3, 4)
}

View File

@ -0,0 +1,3 @@
package t
import _ "internal/does-not-exist"

View File

@ -0,0 +1,6 @@
package p
import (
_ "q/internal/x"
_ "q/j"
)

View File

@ -0,0 +1 @@
package x

View File

@ -0,0 +1,3 @@
package j
import _ "q/internal/x"

View File

@ -0,0 +1,6 @@
package p
import (
_ "q/y"
_ "q/z"
)

View File

@ -0,0 +1 @@
package x

View File

@ -0,0 +1,3 @@
package y
import _ "x"

View File

@ -0,0 +1,3 @@
package z
import _ "q/vendor/x"

View File

@ -0,0 +1,3 @@
package p
import "x"

View File

@ -0,0 +1 @@
package x

View File

@ -5,6 +5,7 @@
package main package main
import ( import (
"flag"
"fmt" "fmt"
"os" "os"
"strconv" "strconv"
@ -16,46 +17,11 @@ import (
// our command line are for us, and some are for 6.out, and // our command line are for us, and some are for 6.out, and
// some are for both. // some are for both.
var usageMessage = `Usage of go test:
-c=false: compile but do not run the test binary
-file=file_test.go: specify file to use for tests;
use multiple times for multiple files
-p=n: build and test up to n packages in parallel
-x=false: print command lines as they are executed
// These flags can be passed with or without a "test." prefix: -v or -test.v.
-bench="": passes -test.bench to test
-benchmem=false: print memory allocation statistics for benchmarks
-benchtime=1s: passes -test.benchtime to test
-cover=false: enable coverage analysis
-covermode="set": specifies mode for coverage analysis
-coverpkg="": comma-separated list of packages for coverage analysis
-coverprofile="": passes -test.coverprofile to test if -cover
-cpu="": passes -test.cpu to test
-cpuprofile="": passes -test.cpuprofile to test
-memprofile="": passes -test.memprofile to test
-memprofilerate=0: passes -test.memprofilerate to test
-blockprofile="": pases -test.blockprofile to test
-blockprofilerate=0: passes -test.blockprofilerate to test
-outputdir=$PWD: passes -test.outputdir to test
-parallel=0: passes -test.parallel to test
-run="": passes -test.run to test
-short=false: passes -test.short to test
-timeout=0: passes -test.timeout to test
-v=false: passes -test.v to test
`
// usage prints a usage message and exits.
func testUsage() {
fmt.Fprint(os.Stderr, usageMessage)
setExitStatus(2)
exit()
}
// testFlagSpec defines a flag we know about. // testFlagSpec defines a flag we know about.
type testFlagSpec struct { type testFlagSpec struct {
name string name string
boolVar *bool boolVar *bool
flagValue flag.Value
passToTest bool // pass to Test passToTest bool // pass to Test
multiOK bool // OK to have multiple instances multiOK bool // OK to have multiple instances
present bool // flag has been seen present bool // flag has been seen
@ -65,32 +31,18 @@ type testFlagSpec struct {
var testFlagDefn = []*testFlagSpec{ var testFlagDefn = []*testFlagSpec{
// local. // local.
{name: "c", boolVar: &testC}, {name: "c", boolVar: &testC},
{name: "cover", boolVar: &testCover},
{name: "coverpkg"},
{name: "o"},
// build flags.
{name: "a", boolVar: &buildA},
{name: "n", boolVar: &buildN},
{name: "p"},
{name: "x", boolVar: &buildX},
{name: "i", boolVar: &buildI}, {name: "i", boolVar: &buildI},
{name: "work", boolVar: &buildWork}, {name: "o"},
{name: "ccflags"}, {name: "cover", boolVar: &testCover},
{name: "gcflags"}, {name: "covermode"},
{name: "coverpkg"},
{name: "exec"}, {name: "exec"},
{name: "ldflags"},
{name: "gccgoflags"},
{name: "tags"},
{name: "compiler"},
{name: "race", boolVar: &buildRace},
{name: "installsuffix"},
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v. // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
{name: "bench", passToTest: true}, {name: "bench", passToTest: true},
{name: "benchmem", boolVar: new(bool), passToTest: true}, {name: "benchmem", boolVar: new(bool), passToTest: true},
{name: "benchtime", passToTest: true}, {name: "benchtime", passToTest: true},
{name: "covermode"}, {name: "count", passToTest: true},
{name: "coverprofile", passToTest: true}, {name: "coverprofile", passToTest: true},
{name: "cpu", passToTest: true}, {name: "cpu", passToTest: true},
{name: "cpuprofile", passToTest: true}, {name: "cpuprofile", passToTest: true},
@ -103,9 +55,26 @@ var testFlagDefn = []*testFlagSpec{
{name: "run", passToTest: true}, {name: "run", passToTest: true},
{name: "short", boolVar: new(bool), passToTest: true}, {name: "short", boolVar: new(bool), passToTest: true},
{name: "timeout", passToTest: true}, {name: "timeout", passToTest: true},
{name: "trace", passToTest: true},
{name: "v", boolVar: &testV, passToTest: true}, {name: "v", boolVar: &testV, passToTest: true},
} }
// add build flags to testFlagDefn
func init() {
var cmd Command
addBuildFlags(&cmd)
cmd.Flag.VisitAll(func(f *flag.Flag) {
if f.Name == "v" {
// test overrides the build -v flag
return
}
testFlagDefn = append(testFlagDefn, &testFlagSpec{
name: f.Name,
flagValue: f.Value,
})
})
}
// testFlags processes the command line, grabbing -x and -c, rewriting known flags // testFlags processes the command line, grabbing -x and -c, rewriting known flags
// to have "test" before them, and reading the command line for the 6.out. // to have "test" before them, and reading the command line for the 6.out.
// Unfortunately for us, we need to do our own flag processing because go test // Unfortunately for us, we need to do our own flag processing because go test
@ -148,51 +117,32 @@ func testFlags(args []string) (packageNames, passToTest []string) {
passToTest = append(passToTest, args[i]) passToTest = append(passToTest, args[i])
continue continue
} }
if f.flagValue != nil {
if err := f.flagValue.Set(value); err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
} else {
// Test-only flags.
// Arguably should be handled by f.flagValue, but aren't.
var err error var err error
switch f.name { switch f.name {
// bool flags. // bool flags.
case "a", "c", "i", "n", "x", "v", "race", "cover", "work": case "c", "i", "v", "cover":
setBoolFlag(f.boolVar, value) setBoolFlag(f.boolVar, value)
case "o": case "o":
testO = value testO = value
testNeedBinary = true testNeedBinary = true
case "p":
setIntFlag(&buildP, value)
case "exec": case "exec":
execCmd, err = splitQuotedFields(value) execCmd, err = splitQuotedFields(value)
if err != nil { if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err) fatalf("invalid flag argument for -%s: %v", f.name, err)
} }
case "ccflags":
buildCcflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "gcflags":
buildGcflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "ldflags":
buildLdflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "gccgoflags":
buildGccgoflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "tags":
buildContext.BuildTags = strings.Fields(value)
case "compiler":
buildCompiler{}.Set(value)
case "bench": case "bench":
// record that we saw the flag; don't care about the value // record that we saw the flag; don't care about the value
testBench = true testBench = true
case "timeout": case "timeout":
testTimeout = value testTimeout = value
case "blockprofile", "cpuprofile", "memprofile": case "blockprofile", "cpuprofile", "memprofile", "trace":
testProfile = true testProfile = true
testNeedBinary = true testNeedBinary = true
case "coverpkg": case "coverpkg":
@ -210,12 +160,13 @@ func testFlags(args []string) (packageNames, passToTest []string) {
case "set", "count", "atomic": case "set", "count", "atomic":
testCoverMode = value testCoverMode = value
default: default:
fatalf("invalid flag argument for -cover: %q", value) fatalf("invalid flag argument for -covermode: %q", value)
} }
testCover = true testCover = true
case "outputdir": case "outputdir":
outputDir = value outputDir = value
} }
}
if extraWord { if extraWord {
i++ i++
} }
@ -267,7 +218,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
for _, f = range testFlagDefn { for _, f = range testFlagDefn {
if name == f.name { if name == f.name {
// Booleans are special because they have modes -x, -x=true, -x=false. // Booleans are special because they have modes -x, -x=true, -x=false.
if f.boolVar != nil { if f.boolVar != nil || isBoolFlag(f.flagValue) {
if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
value = "true" value = "true"
} else { } else {
@ -294,6 +245,17 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
return return
} }
// isBoolFlag reports whether v is a bool flag.
func isBoolFlag(v flag.Value) bool {
vv, ok := v.(interface {
IsBoolFlag() bool
})
if ok {
return vv.IsBoolFlag()
}
return false
}
// setBoolFlag sets the addressed boolean to the value. // setBoolFlag sets the addressed boolean to the value.
func setBoolFlag(flag *bool, value string) { func setBoolFlag(flag *bool, value string) {
x, err := strconv.ParseBool(value) x, err := strconv.ParseBool(value)

View File

@ -50,6 +50,9 @@ func tool(toolName string) string {
if toolIsWindows { if toolIsWindows {
toolPath += toolWindowsExtension toolPath += toolWindowsExtension
} }
if len(buildToolExec) > 0 {
return toolPath
}
// Give a nice message if there is no tool with that name. // Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil { if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) { if isInGoToolsRepo(toolName) {
@ -64,10 +67,6 @@ func tool(toolName string) string {
} }
func isInGoToolsRepo(toolName string) bool { func isInGoToolsRepo(toolName string) bool {
switch toolName {
case "cover", "vet":
return true
}
return false return false
} }
@ -92,7 +91,11 @@ func runTool(cmd *Command, args []string) {
return return
} }
if toolN { if toolN {
fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " ")) cmd := toolPath
if len(args) > 1 {
cmd += " " + strings.Join(args[1:], " ")
}
fmt.Printf("%s\n", cmd)
return return
} }
toolCmd := &exec.Cmd{ toolCmd := &exec.Cmd{
@ -101,6 +104,8 @@ func runTool(cmd *Command, args []string) {
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
Stderr: os.Stderr, Stderr: os.Stderr,
// Set $GOROOT, mainly for go tool dist.
Env: mergeEnvLists([]string{"GOROOT=" + goroot}, os.Environ()),
} }
err := toolCmd.Run() err := toolCmd.Run()
if err != nil { if err != nil {

View File

@ -9,12 +9,15 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"internal/singleflight"
"log" "log"
"net/url"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"sync"
) )
// A vcsCmd describes how to use a version control system // A vcsCmd describes how to use a version control system
@ -23,13 +26,13 @@ type vcsCmd struct {
name string name string
cmd string // name of binary to invoke command cmd string // name of binary to invoke command
createCmd string // command to download a fresh copy of a repository createCmd []string // commands to download a fresh copy of a repository
downloadCmd string // command to download updates into an existing repository downloadCmd []string // commands to download updates into an existing repository
tagCmd []tagCmd // commands to list tags tagCmd []tagCmd // commands to list tags
tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
tagSyncCmd string // command to sync to specific tag tagSyncCmd []string // commands to sync to specific tag
tagSyncDefault string // command to sync to default tag tagSyncDefault []string // commands to sync to default tag
scheme []string scheme []string
pingCmd string pingCmd string
@ -38,6 +41,23 @@ type vcsCmd struct {
resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
} }
var isSecureScheme = map[string]bool{
"https": true,
"git+ssh": true,
"bzr+ssh": true,
"svn+ssh": true,
"ssh": true,
}
func (v *vcsCmd) isSecure(repo string) bool {
u, err := url.Parse(repo)
if err != nil {
// If repo is not a URL, it's not secure.
return false
}
return isSecureScheme[u.Scheme]
}
// A tagCmd describes a command to list available tags // A tagCmd describes a command to list available tags
// that can be passed to tagSyncCmd. // that can be passed to tagSyncCmd.
type tagCmd struct { type tagCmd struct {
@ -69,8 +89,8 @@ var vcsHg = &vcsCmd{
name: "Mercurial", name: "Mercurial",
cmd: "hg", cmd: "hg",
createCmd: "clone -U {repo} {dir}", createCmd: []string{"clone -U {repo} {dir}"},
downloadCmd: "pull", downloadCmd: []string{"pull"},
// We allow both tag and branch names as 'tags' // We allow both tag and branch names as 'tags'
// for selecting a version. This lets people have // for selecting a version. This lets people have
@ -81,8 +101,8 @@ var vcsHg = &vcsCmd{
{"tags", `^(\S+)`}, {"tags", `^(\S+)`},
{"branches", `^(\S+)`}, {"branches", `^(\S+)`},
}, },
tagSyncCmd: "update -r {tag}", tagSyncCmd: []string{"update -r {tag}"},
tagSyncDefault: "update default", tagSyncDefault: []string{"update default"},
scheme: []string{"https", "http", "ssh"}, scheme: []string{"https", "http", "ssh"},
pingCmd: "identify {scheme}://{repo}", pingCmd: "identify {scheme}://{repo}",
@ -102,8 +122,8 @@ var vcsGit = &vcsCmd{
name: "Git", name: "Git",
cmd: "git", cmd: "git",
createCmd: "clone {repo} {dir}", createCmd: []string{"clone {repo} {dir}", "--git-dir={dir}/.git submodule update --init --recursive"},
downloadCmd: "pull --ff-only", downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
tagCmd: []tagCmd{ tagCmd: []tagCmd{
// tags/xxx matches a git tag named xxx // tags/xxx matches a git tag named xxx
@ -113,41 +133,64 @@ var vcsGit = &vcsCmd{
tagLookupCmd: []tagCmd{ tagLookupCmd: []tagCmd{
{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`}, {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
}, },
tagSyncCmd: "checkout {tag}", tagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},
tagSyncDefault: "checkout master", // both createCmd and downloadCmd update the working dir.
// No need to do more here. We used to 'checkout master'
// but that doesn't work if the default branch is not named master.
// See golang.org/issue/9032.
tagSyncDefault: []string{"checkout master", "submodule update --init --recursive"},
scheme: []string{"git", "https", "http", "git+ssh"}, scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
pingCmd: "ls-remote {scheme}://{repo}", pingCmd: "ls-remote {scheme}://{repo}",
remoteRepo: gitRemoteRepo, remoteRepo: gitRemoteRepo,
} }
// scpSyntaxRe matches the SCP-like addresses used by Git to access
// repositories by SSH.
var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) { func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsGit.runOutput(rootDir, "remote -v") cmd := "config remote.origin.url"
errParse := errors.New("unable to parse output of git " + cmd)
errRemoteOriginNotFound := errors.New("remote origin not found")
outb, err := vcsGit.run1(rootDir, cmd, nil, false)
if err != nil {
// if it doesn't output any message, it means the config argument is correct,
// but the config value itself doesn't exist
if outb != nil && len(outb) == 0 {
return "", errRemoteOriginNotFound
}
return "", err
}
out := strings.TrimSpace(string(outb))
var repoURL *url.URL
if m := scpSyntaxRe.FindStringSubmatch(out); m != nil {
// Match SCP-like syntax and convert it to a URL.
// Eg, "git@github.com:user/repo" becomes
// "ssh://git@github.com/user/repo".
repoURL = &url.URL{
Scheme: "ssh",
User: url.User(m[1]),
Host: m[2],
RawPath: m[3],
}
} else {
repoURL, err = url.Parse(out)
if err != nil { if err != nil {
return "", err return "", err
} }
out := string(outb) }
// Expect: // Iterate over insecure schemes too, because this function simply
// origin https://github.com/rsc/pdf (fetch) // reports the state of the repo. If we can't see insecure schemes then
// origin https://github.com/rsc/pdf (push) // we can't report the actual repo URL.
// use first line only. for _, s := range vcsGit.scheme {
if repoURL.Scheme == s {
if !strings.HasPrefix(out, "origin\t") { return repoURL.String(), nil
return "", fmt.Errorf("unable to parse output of git remote -v")
} }
out = strings.TrimPrefix(out, "origin\t")
i := strings.Index(out, "\n")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
} }
out = out[:i] return "", errParse
i = strings.LastIndex(out, " ")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = out[:i]
return strings.TrimSpace(string(out)), nil
} }
// vcsBzr describes how to use Bazaar. // vcsBzr describes how to use Bazaar.
@ -155,15 +198,15 @@ var vcsBzr = &vcsCmd{
name: "Bazaar", name: "Bazaar",
cmd: "bzr", cmd: "bzr",
createCmd: "branch {repo} {dir}", createCmd: []string{"branch {repo} {dir}"},
// Without --overwrite bzr will not pull tags that changed. // Without --overwrite bzr will not pull tags that changed.
// Replace by --overwrite-tags after http://pad.lv/681792 goes in. // Replace by --overwrite-tags after http://pad.lv/681792 goes in.
downloadCmd: "pull --overwrite", downloadCmd: []string{"pull --overwrite"},
tagCmd: []tagCmd{{"tags", `^(\S+)`}}, tagCmd: []tagCmd{{"tags", `^(\S+)`}},
tagSyncCmd: "update -r {tag}", tagSyncCmd: []string{"update -r {tag}"},
tagSyncDefault: "update -r revno:-1", tagSyncDefault: []string{"update -r revno:-1"},
scheme: []string{"https", "http", "bzr", "bzr+ssh"}, scheme: []string{"https", "http", "bzr", "bzr+ssh"},
pingCmd: "info {scheme}://{repo}", pingCmd: "info {scheme}://{repo}",
@ -217,8 +260,8 @@ var vcsSvn = &vcsCmd{
name: "Subversion", name: "Subversion",
cmd: "svn", cmd: "svn",
createCmd: "checkout {repo} {dir}", createCmd: []string{"checkout {repo} {dir}"},
downloadCmd: "update", downloadCmd: []string{"update"},
// There is no tag command in subversion. // There is no tag command in subversion.
// The branch information is all in the path names. // The branch information is all in the path names.
@ -294,14 +337,14 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
_, err := exec.LookPath(v.cmd) _, err := exec.LookPath(v.cmd)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, fmt.Fprintf(os.Stderr,
"go: missing %s command. See http://golang.org/s/gogetcmd\n", "go: missing %s command. See https://golang.org/s/gogetcmd\n",
v.name) v.name)
return nil, err return nil, err
} }
cmd := exec.Command(v.cmd, args...) cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir cmd.Dir = dir
cmd.Env = envForDir(cmd.Dir) cmd.Env = envForDir(cmd.Dir, os.Environ())
if buildX { if buildX {
fmt.Printf("cd %s\n", dir) fmt.Printf("cd %s\n", dir)
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " ")) fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
@ -316,7 +359,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " ")) fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
os.Stderr.Write(out) os.Stderr.Write(out)
} }
return nil, err return out, err
} }
return out, nil return out, nil
} }
@ -329,7 +372,15 @@ func (v *vcsCmd) ping(scheme, repo string) error {
// create creates a new copy of repo in dir. // create creates a new copy of repo in dir.
// The parent of dir must exist; dir must not. // The parent of dir must exist; dir must not.
func (v *vcsCmd) create(dir, repo string) error { func (v *vcsCmd) create(dir, repo string) error {
return v.run(".", v.createCmd, "dir", dir, "repo", repo) for _, cmd := range v.createCmd {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
return err
}
}
return nil
} }
// download downloads any new changes for the repo in dir. // download downloads any new changes for the repo in dir.
@ -337,7 +388,15 @@ func (v *vcsCmd) download(dir string) error {
if err := v.fixDetachedHead(dir); err != nil { if err := v.fixDetachedHead(dir); err != nil {
return err return err
} }
return v.run(dir, v.downloadCmd) for _, cmd := range v.downloadCmd {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd); err != nil {
return err
}
}
return nil
} }
// fixDetachedHead switches a Git repository in dir from a detached head to the master branch. // fixDetachedHead switches a Git repository in dir from a detached head to the master branch.
@ -383,7 +442,7 @@ func (v *vcsCmd) tags(dir string) ([]string, error) {
// tagSync syncs the repo in dir to the named tag, // tagSync syncs the repo in dir to the named tag,
// which either is a tag returned by tags or is v.tagDefault. // which either is a tag returned by tags or is v.tagDefault.
func (v *vcsCmd) tagSync(dir, tag string) error { func (v *vcsCmd) tagSync(dir, tag string) error {
if v.tagSyncCmd == "" { if v.tagSyncCmd == nil {
return nil return nil
} }
if tag != "" { if tag != "" {
@ -400,10 +459,28 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
} }
} }
} }
if tag == "" && v.tagSyncDefault != "" {
return v.run(dir, v.tagSyncDefault) if tag == "" && v.tagSyncDefault != nil {
for _, cmd := range v.tagSyncDefault {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
} }
return v.run(dir, v.tagSyncCmd, "tag", tag) if err := v.run(dir, cmd); err != nil {
return err
}
}
return nil
}
for _, cmd := range v.tagSyncCmd {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd, "tag", tag); err != nil {
return err
}
}
return nil
} }
// A vcsPath describes how to convert an import path into a // A vcsPath describes how to convert an import path into a
@ -467,10 +544,20 @@ type repoRoot struct {
var httpPrefixRE = regexp.MustCompile(`^https?:`) var httpPrefixRE = regexp.MustCompile(`^https?:`)
// securityMode specifies whether a function should make network
// calls using insecure transports (eg, plain text HTTP).
// The zero value is "secure".
type securityMode int
const (
secure securityMode = iota
insecure
)
// repoRootForImportPath analyzes importPath to determine the // repoRootForImportPath analyzes importPath to determine the
// version control system, and code repository to use. // version control system, and code repository to use.
func repoRootForImportPath(importPath string) (*repoRoot, error) { func repoRootForImportPath(importPath string, security securityMode) (*repoRoot, error) {
rr, err := repoRootForImportPathStatic(importPath, "") rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths)
if err == errUnknownSite { if err == errUnknownSite {
// If there are wildcards, look up the thing before the wildcard, // If there are wildcards, look up the thing before the wildcard,
// hoping it applies to the wildcarded parts too. // hoping it applies to the wildcarded parts too.
@ -479,7 +566,7 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
if i := strings.Index(lookup, "/.../"); i >= 0 { if i := strings.Index(lookup, "/.../"); i >= 0 {
lookup = lookup[:i] lookup = lookup[:i]
} }
rr, err = repoRootForImportDynamic(lookup) rr, err = repoRootForImportDynamic(lookup, security)
// repoRootForImportDynamic returns error detail // repoRootForImportDynamic returns error detail
// that is irrelevant if the user didn't intend to use a // that is irrelevant if the user didn't intend to use a
@ -492,6 +579,13 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
err = fmt.Errorf("unrecognized import path %q", importPath) err = fmt.Errorf("unrecognized import path %q", importPath)
} }
} }
if err != nil {
rr1, err1 := repoRootFromVCSPaths(importPath, "", security, vcsPathsAfterDynamic)
if err1 == nil {
rr = rr1
err = nil
}
}
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") { if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") {
// Do not allow wildcards in the repo root. // Do not allow wildcards in the repo root.
@ -503,13 +597,10 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
var errUnknownSite = errors.New("dynamic lookup required to find mapping") var errUnknownSite = errors.New("dynamic lookup required to find mapping")
// repoRootForImportPathStatic attempts to map importPath to a // repoRootFromVCSPaths attempts to map importPath to a repoRoot
// repoRoot using the commonly-used VCS hosting sites in vcsPaths // using the mappings defined in vcsPaths.
// (github.com/user/dir), or from a fully-qualified importPath already
// containing its VCS type (foo.com/repo.git/dir)
//
// If scheme is non-empty, that scheme is forced. // If scheme is non-empty, that scheme is forced.
func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) { func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsPaths []*vcsPath) (*repoRoot, error) {
// A common error is to use https://packagepath because that's what // A common error is to use https://packagepath because that's what
// hg and git require. Diagnose this helpfully. // hg and git require. Diagnose this helpfully.
if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil { if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil {
@ -559,6 +650,9 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
match["repo"] = scheme + "://" + match["repo"] match["repo"] = scheme + "://" + match["repo"]
} else { } else {
for _, scheme := range vcs.scheme { for _, scheme := range vcs.scheme {
if security == secure && !isSecureScheme[scheme] {
continue
}
if vcs.ping(scheme, match["repo"]) == nil { if vcs.ping(scheme, match["repo"]) == nil {
match["repo"] = scheme + "://" + match["repo"] match["repo"] = scheme + "://" + match["repo"]
break break
@ -579,26 +673,31 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not // repoRootForImportDynamic finds a *repoRoot for a custom domain that's not
// statically known by repoRootForImportPathStatic. // statically known by repoRootForImportPathStatic.
// //
// This handles "vanity import paths" like "name.tld/pkg/foo". // This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".
func repoRootForImportDynamic(importPath string) (*repoRoot, error) { func repoRootForImportDynamic(importPath string, security securityMode) (*repoRoot, error) {
slash := strings.Index(importPath, "/") slash := strings.Index(importPath, "/")
if slash < 0 { if slash < 0 {
return nil, errors.New("import path does not contain a slash") slash = len(importPath)
} }
host := importPath[:slash] host := importPath[:slash]
if !strings.Contains(host, ".") { if !strings.Contains(host, ".") {
return nil, errors.New("import path does not begin with hostname") return nil, errors.New("import path does not begin with hostname")
} }
urlStr, body, err := httpsOrHTTP(importPath) urlStr, body, err := httpsOrHTTP(importPath, security)
if err != nil { if err != nil {
return nil, fmt.Errorf("http/https fetch: %v", err) msg := "https fetch: %v"
if security == insecure {
msg = "http/" + msg
}
return nil, fmt.Errorf(msg, err)
} }
defer body.Close() defer body.Close()
imports, err := parseMetaGoImports(body) imports, err := parseMetaGoImports(body)
if err != nil { if err != nil {
return nil, fmt.Errorf("parsing %s: %v", importPath, err) return nil, fmt.Errorf("parsing %s: %v", importPath, err)
} }
metaImport, err := matchGoImport(imports, importPath) // Find the matched meta import.
mmi, err := matchGoImport(imports, importPath)
if err != nil { if err != nil {
if err != errNoMatch { if err != errNoMatch {
return nil, fmt.Errorf("parse %s: %v", urlStr, err) return nil, fmt.Errorf("parse %s: %v", urlStr, err)
@ -606,7 +705,7 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr) return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
} }
if buildV { if buildV {
log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr) log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr)
} }
// If the import was "uni.edu/bob/project", which said the // If the import was "uni.edu/bob/project", which said the
// prefix was "uni.edu" and the RepoRoot was "evilroot.com", // prefix was "uni.edu" and the RepoRoot was "evilroot.com",
@ -614,42 +713,89 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
// "uni.edu" yet (possibly overwriting/preempting another // "uni.edu" yet (possibly overwriting/preempting another
// non-evil student). Instead, first verify the root and see // non-evil student). Instead, first verify the root and see
// if it matches Bob's claim. // if it matches Bob's claim.
if metaImport.Prefix != importPath { if mmi.Prefix != importPath {
if buildV { if buildV {
log.Printf("get %q: verifying non-authoritative meta tag", importPath) log.Printf("get %q: verifying non-authoritative meta tag", importPath)
} }
urlStr0 := urlStr urlStr0 := urlStr
urlStr, body, err = httpsOrHTTP(metaImport.Prefix) var imports []metaImport
urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, security)
if err != nil { if err != nil {
return nil, fmt.Errorf("fetch %s: %v", urlStr, err) return nil, err
}
imports, err := parseMetaGoImports(body)
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", importPath, err)
}
if len(imports) == 0 {
return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
} }
metaImport2, err := matchGoImport(imports, importPath) metaImport2, err := matchGoImport(imports, importPath)
if err != nil || metaImport != metaImport2 { if err != nil || mmi != metaImport2 {
return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix) return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, mmi.Prefix)
} }
} }
if !strings.Contains(metaImport.RepoRoot, "://") { if !strings.Contains(mmi.RepoRoot, "://") {
return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot) return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot)
} }
rr := &repoRoot{ rr := &repoRoot{
vcs: vcsByCmd(metaImport.VCS), vcs: vcsByCmd(mmi.VCS),
repo: metaImport.RepoRoot, repo: mmi.RepoRoot,
root: metaImport.Prefix, root: mmi.Prefix,
} }
if rr.vcs == nil { if rr.vcs == nil {
return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS) return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS)
} }
return rr, nil return rr, nil
} }
var fetchGroup singleflight.Group
var (
fetchCacheMu sync.Mutex
fetchCache = map[string]fetchResult{} // key is metaImportsForPrefix's importPrefix
)
// metaImportsForPrefix takes a package's root import path as declared in a <meta> tag
// and returns its HTML discovery URL and the parsed metaImport lines
// found on the page.
//
// The importPath is of the form "golang.org/x/tools".
// It is an error if no imports are found.
// urlStr will still be valid if err != nil.
// The returned urlStr will be of the form "https://golang.org/x/tools?go-get=1"
func metaImportsForPrefix(importPrefix string, security securityMode) (urlStr string, imports []metaImport, err error) {
setCache := func(res fetchResult) (fetchResult, error) {
fetchCacheMu.Lock()
defer fetchCacheMu.Unlock()
fetchCache[importPrefix] = res
return res, nil
}
resi, _, _ := fetchGroup.Do(importPrefix, func() (resi interface{}, err error) {
fetchCacheMu.Lock()
if res, ok := fetchCache[importPrefix]; ok {
fetchCacheMu.Unlock()
return res, nil
}
fetchCacheMu.Unlock()
urlStr, body, err := httpsOrHTTP(importPrefix, security)
if err != nil {
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)})
}
imports, err := parseMetaGoImports(body)
if err != nil {
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("parsing %s: %v", urlStr, err)})
}
if len(imports) == 0 {
err = fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
}
return setCache(fetchResult{urlStr: urlStr, imports: imports, err: err})
})
res := resi.(fetchResult)
return res.urlStr, res.imports, res.err
}
type fetchResult struct {
urlStr string // e.g. "https://foo.com/x/bar?go-get=1"
imports []metaImport
err error
}
// metaImport represents the parsed <meta name="go-import" // metaImport represents the parsed <meta name="go-import"
// content="prefix vcs reporoot" /> tags from HTML files. // content="prefix vcs reporoot" /> tags from HTML files.
type metaImport struct { type metaImport struct {
@ -689,7 +835,10 @@ func expand(match map[string]string, s string) string {
return s return s
} }
// vcsPaths lists the known vcs paths. // vcsPaths defines the meaning of import paths referring to
// commonly-used VCS hosting sites (github.com/user/dir)
// and import paths referring to a fully-qualified importPath
// containing a VCS type (foo.com/repo.git/dir)
var vcsPaths = []*vcsPath{ var vcsPaths = []*vcsPath{
// Google Code - new syntax // Google Code - new syntax
{ {
@ -722,15 +871,6 @@ var vcsPaths = []*vcsPath{
check: bitbucketVCS, check: bitbucketVCS,
}, },
// Launchpad
{
prefix: "launchpad.net/",
re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
vcs: "bzr",
repo: "https://{root}",
check: launchpadVCS,
},
// IBM DevOps Services (JazzHub) // IBM DevOps Services (JazzHub)
{ {
prefix: "hub.jazz.net/git", prefix: "hub.jazz.net/git",
@ -740,13 +880,37 @@ var vcsPaths = []*vcsPath{
check: noVCSSuffix, check: noVCSSuffix,
}, },
// Git at Apache
{
prefix: "git.apache.org",
re: `^(?P<root>git.apache.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`,
vcs: "git",
repo: "https://{root}",
},
// General syntax for any server. // General syntax for any server.
// Must be last.
{ {
re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`, re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
ping: true, ping: true,
}, },
} }
// vcsPathsAfterDynamic gives additional vcsPaths entries
// to try after the dynamic HTML check.
// This gives those sites a chance to introduce <meta> tags
// as part of a graceful transition away from the hard-coded logic.
var vcsPathsAfterDynamic = []*vcsPath{
// Launchpad. See golang.org/issue/11436.
{
prefix: "launchpad.net/",
re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
vcs: "bzr",
repo: "https://{root}",
check: launchpadVCS,
},
}
func init() { func init() {
// fill in cached regexps. // fill in cached regexps.
// Doing this eagerly discovers invalid regexp syntax // Doing this eagerly discovers invalid regexp syntax
@ -754,6 +918,9 @@ func init() {
for _, srv := range vcsPaths { for _, srv := range vcsPaths {
srv.regexp = regexp.MustCompile(srv.re) srv.regexp = regexp.MustCompile(srv.re)
} }
for _, srv := range vcsPathsAfterDynamic {
srv.regexp = regexp.MustCompile(srv.re)
}
} }
// noVCSSuffix checks that the repository name does not // noVCSSuffix checks that the repository name does not
@ -821,11 +988,26 @@ func bitbucketVCS(match map[string]string) error {
url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}") url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
data, err := httpGET(url) data, err := httpGET(url)
if err != nil { if err != nil {
if httpErr, ok := err.(*httpError); ok && httpErr.statusCode == 403 {
// this may be a private repository. If so, attempt to determine which
// VCS it uses. See issue 5375.
root := match["root"]
for _, vcs := range []string{"git", "hg"} {
if vcsByCmd(vcs).ping("https", root) == nil {
resp.SCM = vcs
break
}
}
}
if resp.SCM == "" {
return err return err
} }
} else {
if err := json.Unmarshal(data, &resp); err != nil { if err := json.Unmarshal(data, &resp); err != nil {
return fmt.Errorf("decoding %s: %v", url, err) return fmt.Errorf("decoding %s: %v", url, err)
} }
}
if vcsByCmd(resp.SCM) != nil { if vcsByCmd(resp.SCM) != nil {
match["vcs"] = resp.SCM match["vcs"] = resp.SCM

Some files were not shown because too many files have changed in this diff Show More