golang.sh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. #!/bin/bash
  2. # Copyright 2014 The Kubernetes Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # The golang package that we are building.
  16. readonly KUBE_GO_PACKAGE=k8s.io/kubernetes
  17. readonly KUBE_GOPATH="${KUBE_OUTPUT}/go"
  18. # Load contrib target functions
  19. if [ -n "${KUBERNETES_CONTRIB:-}" ]; then
  20. for contrib in "${KUBERNETES_CONTRIB}"; do
  21. source "${KUBE_ROOT}/contrib/${contrib}/target.sh"
  22. done
  23. fi
  24. # The set of server targets that we are only building for Linux
  25. # Note: if you are adding something here, you might need to add it to
  26. # kube::build::source_targets in build/common.sh as well.
  27. kube::golang::server_targets() {
  28. local targets=(
  29. cmd/kube-dns
  30. cmd/kube-proxy
  31. cmd/kube-apiserver
  32. cmd/kube-controller-manager
  33. cmd/kubelet
  34. cmd/kubemark
  35. cmd/hyperkube
  36. plugin/cmd/kube-scheduler
  37. )
  38. if [ -n "${KUBERNETES_CONTRIB:-}" ]; then
  39. for contrib in "${KUBERNETES_CONTRIB}"; do
  40. targets+=($(eval "kube::contrib::${contrib}::server_targets"))
  41. done
  42. fi
  43. echo "${targets[@]}"
  44. }
  45. readonly KUBE_SERVER_TARGETS=($(kube::golang::server_targets))
  46. readonly KUBE_SERVER_BINARIES=("${KUBE_SERVER_TARGETS[@]##*/}")
  47. if [[ "${KUBE_FASTBUILD:-}" == "true" ]]; then
  48. readonly KUBE_SERVER_PLATFORMS=(linux/amd64)
  49. if [[ "${KUBE_BUILDER_OS:-}" == "darwin"* ]]; then
  50. readonly KUBE_TEST_PLATFORMS=(
  51. darwin/amd64
  52. linux/amd64
  53. )
  54. readonly KUBE_CLIENT_PLATFORMS=(
  55. darwin/amd64
  56. linux/amd64
  57. )
  58. else
  59. readonly KUBE_TEST_PLATFORMS=(linux/amd64)
  60. readonly KUBE_CLIENT_PLATFORMS=(linux/amd64)
  61. fi
  62. else
  63. # The server platform we are building on.
  64. KUBE_SERVER_PLATFORMS=(
  65. linux/amd64
  66. linux/arm
  67. linux/arm64
  68. )
  69. if [[ "${KUBE_BUILD_PPC64LE:-}" =~ ^[yY]$ ]]; then
  70. KUBE_SERVER_PLATFORMS+=(linux/ppc64le)
  71. fi
  72. readonly KUBE_SERVER_PLATFORMS
  73. # If we update this we should also update the set of golang compilers we build
  74. # in 'build/build-image/cross/Dockerfile'. However, it's only a bit faster since go 1.5, not mandatory
  75. KUBE_CLIENT_PLATFORMS=(
  76. linux/amd64
  77. linux/386
  78. linux/arm
  79. linux/arm64
  80. darwin/amd64
  81. darwin/386
  82. windows/amd64
  83. windows/386
  84. )
  85. if [[ "${KUBE_BUILD_PPC64LE:-}" =~ ^[yY]$ ]]; then
  86. KUBE_CLIENT_PLATFORMS+=(linux/ppc64le)
  87. fi
  88. readonly KUBE_CLIENT_PLATFORMS
  89. # Which platforms we should compile test targets for. Not all client platforms need these tests
  90. readonly KUBE_TEST_PLATFORMS=(
  91. linux/amd64
  92. darwin/amd64
  93. windows/amd64
  94. linux/arm
  95. )
  96. fi
  97. # The set of client targets that we are building for all platforms
  98. readonly KUBE_CLIENT_TARGETS=(
  99. cmd/kubectl
  100. )
  101. readonly KUBE_CLIENT_BINARIES=("${KUBE_CLIENT_TARGETS[@]##*/}")
  102. readonly KUBE_CLIENT_BINARIES_WIN=("${KUBE_CLIENT_BINARIES[@]/%/.exe}")
  103. # The set of test targets that we are building for all platforms
  104. kube::golang::test_targets() {
  105. local targets=(
  106. cmd/gendocs
  107. cmd/genkubedocs
  108. cmd/genman
  109. cmd/genyaml
  110. cmd/mungedocs
  111. cmd/genswaggertypedocs
  112. cmd/linkcheck
  113. examples/k8petstore/web-server/src
  114. federation/cmd/genfeddocs
  115. vendor/github.com/onsi/ginkgo/ginkgo
  116. test/e2e/e2e.test
  117. test/e2e_node/e2e_node.test
  118. )
  119. if [ -n "${KUBERNETES_CONTRIB:-}" ]; then
  120. for contrib in "${KUBERNETES_CONTRIB}"; do
  121. targets+=($(eval "kube::contrib::${contrib}::test_targets"))
  122. done
  123. fi
  124. echo "${targets[@]}"
  125. }
  126. readonly KUBE_TEST_TARGETS=($(kube::golang::test_targets))
  127. readonly KUBE_TEST_BINARIES=("${KUBE_TEST_TARGETS[@]##*/}")
  128. readonly KUBE_TEST_BINARIES_WIN=("${KUBE_TEST_BINARIES[@]/%/.exe}")
  129. readonly KUBE_TEST_PORTABLE=(
  130. test/e2e/testing-manifests
  131. test/kubemark
  132. hack/e2e.go
  133. hack/e2e-internal
  134. hack/get-build.sh
  135. hack/ginkgo-e2e.sh
  136. hack/federated-ginkgo-e2e.sh
  137. hack/lib
  138. )
  139. # Gigabytes desired for parallel platform builds. 11 is fairly
  140. # arbitrary, but is a reasonable splitting point for 2015
  141. # laptops-versus-not.
  142. #
  143. # If you are using boot2docker, the following seems to work (note
  144. # that 12000 rounds to 11G):
  145. # boot2docker down
  146. # VBoxManage modifyvm boot2docker-vm --memory 12000
  147. # boot2docker up
  148. readonly KUBE_PARALLEL_BUILD_MEMORY=11
  149. readonly KUBE_ALL_TARGETS=(
  150. "${KUBE_SERVER_TARGETS[@]}"
  151. "${KUBE_CLIENT_TARGETS[@]}"
  152. "${KUBE_TEST_TARGETS[@]}"
  153. )
  154. readonly KUBE_ALL_BINARIES=("${KUBE_ALL_TARGETS[@]##*/}")
  155. readonly KUBE_STATIC_LIBRARIES=(
  156. kube-apiserver
  157. kube-controller-manager
  158. kube-dns
  159. kube-scheduler
  160. kube-proxy
  161. kubectl
  162. )
  163. kube::golang::is_statically_linked_library() {
  164. local e
  165. for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done;
  166. # Allow individual overrides--e.g., so that you can get a static build of
  167. # kubectl for inclusion in a container.
  168. if [ -n "${KUBE_STATIC_OVERRIDES:+x}" ]; then
  169. for e in "${KUBE_STATIC_OVERRIDES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done;
  170. fi
  171. return 1;
  172. }
  173. # kube::binaries_from_targets take a list of build targets and return the
  174. # full go package to be built
  175. kube::golang::binaries_from_targets() {
  176. local target
  177. for target; do
  178. # If the target starts with what looks like a domain name, assume it has a
  179. # fully-qualified package name rather than one that needs the Kubernetes
  180. # package prepended.
  181. if [[ "${target}" =~ ^([[:alnum:]]+".")+[[:alnum:]]+"/" ]]; then
  182. echo "${target}"
  183. else
  184. echo "${KUBE_GO_PACKAGE}/${target}"
  185. fi
  186. done
  187. }
  188. # Asks golang what it thinks the host platform is. The go tool chain does some
  189. # slightly different things when the target platform matches the host platform.
  190. kube::golang::host_platform() {
  191. echo "$(go env GOHOSTOS)/$(go env GOHOSTARCH)"
  192. }
  193. kube::golang::current_platform() {
  194. local os="${GOOS-}"
  195. if [[ -z $os ]]; then
  196. os=$(go env GOHOSTOS)
  197. fi
  198. local arch="${GOARCH-}"
  199. if [[ -z $arch ]]; then
  200. arch=$(go env GOHOSTARCH)
  201. fi
  202. echo "$os/$arch"
  203. }
  204. # Takes the the platform name ($1) and sets the appropriate golang env variables
  205. # for that platform.
  206. kube::golang::set_platform_envs() {
  207. [[ -n ${1-} ]] || {
  208. kube::log::error_exit "!!! Internal error. No platform set in kube::golang::set_platform_envs"
  209. }
  210. export GOOS=${platform%/*}
  211. export GOARCH=${platform##*/}
  212. # Do not set CC when building natively on a platform, only if cross-compiling from linux/amd64
  213. if [[ $(kube::golang::host_platform) == "linux/amd64" ]]; then
  214. # Dynamic CGO linking for other server architectures than linux/amd64 goes here
  215. # If you want to include support for more server platforms than these, add arch-specific gcc names here
  216. if [[ ${platform} == "linux/arm" ]]; then
  217. export CGO_ENABLED=1
  218. export CC=arm-linux-gnueabi-gcc
  219. elif [[ ${platform} == "linux/arm64" ]]; then
  220. export CGO_ENABLED=1
  221. export CC=aarch64-linux-gnu-gcc
  222. elif [[ ${platform} == "linux/ppc64le" ]]; then
  223. export CGO_ENABLED=1
  224. export CC=powerpc64le-linux-gnu-gcc
  225. fi
  226. fi
  227. }
  228. kube::golang::unset_platform_envs() {
  229. unset GOOS
  230. unset GOARCH
  231. unset CGO_ENABLED
  232. unset CC
  233. }
  234. # Create the GOPATH tree under $KUBE_OUTPUT
  235. kube::golang::create_gopath_tree() {
  236. local go_pkg_dir="${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}"
  237. local go_pkg_basedir=$(dirname "${go_pkg_dir}")
  238. mkdir -p "${go_pkg_basedir}"
  239. # TODO: This symlink should be relative.
  240. if [[ ! -e "${go_pkg_dir}" || "$(readlink ${go_pkg_dir})" != "${KUBE_ROOT}" ]]; then
  241. ln -snf "${KUBE_ROOT}" "${go_pkg_dir}"
  242. fi
  243. }
  244. # Ensure the godep tool exists and is a viable version.
  245. kube::golang::verify_godep_version() {
  246. local -a godep_version_string
  247. local godep_version
  248. local godep_min_version="63"
  249. if ! which godep &>/dev/null; then
  250. kube::log::usage_from_stdin <<EOF
  251. Can't find 'godep' in PATH, please fix and retry.
  252. See https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md#godep-and-dependency-management for installation instructions.
  253. EOF
  254. return 2
  255. fi
  256. godep_version_string=($(godep version))
  257. godep_version=${godep_version_string[1]/v/}
  258. if ((godep_version<$godep_min_version)); then
  259. kube::log::usage_from_stdin <<EOF
  260. Detected godep version: ${godep_version_string[*]}.
  261. Kubernetes requires godep v$godep_min_version or greater.
  262. Please update:
  263. go get -u github.com/tools/godep
  264. EOF
  265. return 2
  266. fi
  267. }
  268. # Ensure the go tool exists and is a viable version.
  269. kube::golang::verify_go_version() {
  270. if [[ -z "$(which go)" ]]; then
  271. kube::log::usage_from_stdin <<EOF
  272. Can't find 'go' in PATH, please fix and retry.
  273. See http://golang.org/doc/install for installation instructions.
  274. EOF
  275. return 2
  276. fi
  277. local go_version
  278. go_version=($(go version))
  279. if [[ "${go_version[2]}" < "go1.6" && "${go_version[2]}" != "devel" ]]; then
  280. kube::log::usage_from_stdin <<EOF
  281. Detected go version: ${go_version[*]}.
  282. Kubernetes requires go version 1.6 or greater.
  283. Please install Go version 1.6 or later.
  284. EOF
  285. return 2
  286. fi
  287. }
  288. # kube::golang::setup_env will check that the `go` commands is available in
  289. # ${PATH}. It will also check that the Go version is good enough for the
  290. # Kubernetes build.
  291. #
  292. # Inputs:
  293. # KUBE_EXTRA_GOPATH - If set, this is included in created GOPATH
  294. #
  295. # Outputs:
  296. # env-var GOPATH points to our local output dir
  297. # env-var GOBIN is unset (we want binaries in a predictable place)
  298. # env-var GO15VENDOREXPERIMENT=1
  299. # current directory is within GOPATH
  300. kube::golang::setup_env() {
  301. kube::golang::verify_go_version
  302. kube::golang::create_gopath_tree
  303. export GOPATH=${KUBE_GOPATH}
  304. # Append KUBE_EXTRA_GOPATH to the GOPATH if it is defined.
  305. if [[ -n ${KUBE_EXTRA_GOPATH:-} ]]; then
  306. GOPATH="${GOPATH}:${KUBE_EXTRA_GOPATH}"
  307. fi
  308. # Change directories so that we are within the GOPATH. Some tools get really
  309. # upset if this is not true. We use a whole fake GOPATH here to collect the
  310. # resultant binaries. Go will not let us use GOBIN with `go install` and
  311. # cross-compiling, and `go install -o <file>` only works for a single pkg.
  312. local subdir
  313. subdir=$(kube::realpath . | sed "s|$KUBE_ROOT||")
  314. cd "${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}/${subdir}"
  315. # Set GOROOT so binaries that parse code can work properly.
  316. export GOROOT=$(go env GOROOT)
  317. # Unset GOBIN in case it already exists in the current session.
  318. unset GOBIN
  319. # This seems to matter to some tools (godep, ugorji, ginkgo...)
  320. export GO15VENDOREXPERIMENT=1
  321. }
  322. # This will take binaries from $GOPATH/bin and copy them to the appropriate
  323. # place in ${KUBE_OUTPUT_BINDIR}
  324. #
  325. # Ideally this wouldn't be necessary and we could just set GOBIN to
  326. # KUBE_OUTPUT_BINDIR but that won't work in the face of cross compilation. 'go
  327. # install' will place binaries that match the host platform directly in $GOBIN
  328. # while placing cross compiled binaries into `platform_arch` subdirs. This
  329. # complicates pretty much everything else we do around packaging and such.
  330. kube::golang::place_bins() {
  331. local host_platform
  332. host_platform=$(kube::golang::host_platform)
  333. V=2 kube::log::status "Placing binaries"
  334. local platform
  335. for platform in "${KUBE_CLIENT_PLATFORMS[@]}"; do
  336. # The substitution on platform_src below will replace all slashes with
  337. # underscores. It'll transform darwin/amd64 -> darwin_amd64.
  338. local platform_src="/${platform//\//_}"
  339. if [[ $platform == $host_platform ]]; then
  340. platform_src=""
  341. rm -f "${THIS_PLATFORM_BIN}"
  342. ln -s "${KUBE_OUTPUT_BINPATH}/${platform}" "${THIS_PLATFORM_BIN}"
  343. fi
  344. local full_binpath_src="${KUBE_GOPATH}/bin${platform_src}"
  345. if [[ -d "${full_binpath_src}" ]]; then
  346. mkdir -p "${KUBE_OUTPUT_BINPATH}/${platform}"
  347. find "${full_binpath_src}" -maxdepth 1 -type f -exec \
  348. rsync -pt {} "${KUBE_OUTPUT_BINPATH}/${platform}" \;
  349. fi
  350. done
  351. }
  352. kube::golang::fallback_if_stdlib_not_installable() {
  353. local go_root_dir=$(go env GOROOT);
  354. local go_host_os=$(go env GOHOSTOS);
  355. local go_host_arch=$(go env GOHOSTARCH);
  356. local cgo_pkg_dir=${go_root_dir}/pkg/${go_host_os}_${go_host_arch}_cgo;
  357. if [ -e ${cgo_pkg_dir} ]; then
  358. return 0;
  359. fi
  360. if [ -w ${go_root_dir}/pkg ]; then
  361. return 0;
  362. fi
  363. kube::log::status "+++ Warning: stdlib pkg with cgo flag not found.";
  364. kube::log::status "+++ Warning: stdlib pkg cannot be rebuilt since ${go_root_dir}/pkg is not writable by `whoami`";
  365. kube::log::status "+++ Warning: Make ${go_root_dir}/pkg writable for `whoami` for a one-time stdlib install, Or"
  366. kube::log::status "+++ Warning: Rebuild stdlib using the command 'CGO_ENABLED=0 go install -a -installsuffix cgo std'";
  367. kube::log::status "+++ Falling back to go build, which is slower";
  368. use_go_build=true
  369. }
  370. # Builds the toolchain necessary for building kube. This needs to be
  371. # built only on the host platform.
  372. # TODO: This builds only the `teststale` binary right now. As we expand
  373. # this function's capabilities we need to find this a right home.
  374. # Ideally, not a shell script because testing shell scripts is painful.
  375. kube::golang::build_kube_toolchain() {
  376. local targets=(
  377. hack/cmd/teststale
  378. )
  379. local binaries
  380. binaries=($(kube::golang::binaries_from_targets "${targets[@]}"))
  381. kube::log::status "Building the toolchain targets:" "${binaries[@]}"
  382. go install "${goflags[@]:+${goflags[@]}}" \
  383. -gcflags "${gogcflags}" \
  384. -ldflags "${goldflags}" \
  385. "${binaries[@]:+${binaries[@]}}"
  386. }
  387. # Try and replicate the native binary placement of go install without
  388. # calling go install.
  389. kube::golang::output_filename_for_binary() {
  390. local binary=$1
  391. local platform=$2
  392. local output_path="${KUBE_GOPATH}/bin"
  393. if [[ $platform != $host_platform ]]; then
  394. output_path="${output_path}/${platform//\//_}"
  395. fi
  396. local bin=$(basename "${binary}")
  397. if [[ ${GOOS} == "windows" ]]; then
  398. bin="${bin}.exe"
  399. fi
  400. echo "${output_path}/${bin}"
  401. }
  402. kube::golang::build_binaries_for_platform() {
  403. local platform=$1
  404. local use_go_build=${2-}
  405. local -a statics=()
  406. local -a nonstatics=()
  407. local -a tests=()
  408. for binary in "${binaries[@]}"; do
  409. if [[ "${binary}" =~ ".test"$ ]]; then
  410. tests+=($binary)
  411. elif kube::golang::is_statically_linked_library "${binary}"; then
  412. statics+=($binary)
  413. else
  414. nonstatics+=($binary)
  415. fi
  416. done
  417. if [[ "${#statics[@]}" != 0 ]]; then
  418. kube::golang::fallback_if_stdlib_not_installable;
  419. fi
  420. if [[ -n ${use_go_build:-} ]]; then
  421. kube::log::progress " "
  422. for binary in "${statics[@]:+${statics[@]}}"; do
  423. local outfile=$(kube::golang::output_filename_for_binary "${binary}" "${platform}")
  424. CGO_ENABLED=0 go build -o "${outfile}" \
  425. "${goflags[@]:+${goflags[@]}}" \
  426. -gcflags "${gogcflags}" \
  427. -ldflags "${goldflags}" \
  428. "${binary}"
  429. kube::log::progress "*"
  430. done
  431. for binary in "${nonstatics[@]:+${nonstatics[@]}}"; do
  432. local outfile=$(kube::golang::output_filename_for_binary "${binary}" "${platform}")
  433. go build -o "${outfile}" \
  434. "${goflags[@]:+${goflags[@]}}" \
  435. -gcflags "${gogcflags}" \
  436. -ldflags "${goldflags}" \
  437. "${binary}"
  438. kube::log::progress "*"
  439. done
  440. kube::log::progress "\n"
  441. else
  442. # Use go install.
  443. if [[ "${#nonstatics[@]}" != 0 ]]; then
  444. go install "${goflags[@]:+${goflags[@]}}" \
  445. -gcflags "${gogcflags}" \
  446. -ldflags "${goldflags}" \
  447. "${nonstatics[@]:+${nonstatics[@]}}"
  448. fi
  449. if [[ "${#statics[@]}" != 0 ]]; then
  450. CGO_ENABLED=0 go install -installsuffix cgo "${goflags[@]:+${goflags[@]}}" \
  451. -gcflags "${gogcflags}" \
  452. -ldflags "${goldflags}" \
  453. "${statics[@]:+${statics[@]}}"
  454. fi
  455. fi
  456. for test in "${tests[@]:+${tests[@]}}"; do
  457. local outfile=$(kube::golang::output_filename_for_binary "${test}" \
  458. "${platform}")
  459. local testpkg="$(dirname ${test})"
  460. # Staleness check always happens on the host machine, so we don't
  461. # have to locate the `teststale` binaries for the other platforms.
  462. # Since we place the host binaries in `$KUBE_GOPATH/bin`, we can
  463. # assume that the binary exists there, if it exists at all.
  464. # Otherwise, something has gone wrong with building the `teststale`
  465. # binary and we should safely proceed building the test binaries
  466. # assuming that they are stale. There is no good reason to error
  467. # out.
  468. if test -x "${KUBE_GOPATH}/bin/teststale" && ! "${KUBE_GOPATH}/bin/teststale" -binary "${outfile}" -package "${testpkg}"
  469. then
  470. continue
  471. fi
  472. # `go test -c` below directly builds the binary. It builds the packages,
  473. # but it never installs them. `go test -i` only installs the dependencies
  474. # of the test, but not the test package itself. So neither `go test -c`
  475. # nor `go test -i` installs, for example, test/e2e.a. And without that,
  476. # doing a staleness check on k8s.io/kubernetes/test/e2e package always
  477. # returns true (always stale). And that's why we need to install the
  478. # test package.
  479. go install "${goflags[@]:+${goflags[@]}}" \
  480. -gcflags "${gogcflags}" \
  481. -ldflags "${goldflags}" \
  482. "${testpkg}"
  483. mkdir -p "$(dirname ${outfile})"
  484. go test -c \
  485. "${goflags[@]:+${goflags[@]}}" \
  486. -gcflags "${gogcflags}" \
  487. -ldflags "${goldflags}" \
  488. -o "${outfile}" \
  489. "${testpkg}"
  490. done
  491. }
  492. # Return approximate physical memory available in gigabytes.
  493. kube::golang::get_physmem() {
  494. local mem
  495. # Linux kernel version >=3.14, in kb
  496. if mem=$(grep MemAvailable /proc/meminfo | awk '{ print $2 }'); then
  497. echo $(( ${mem} / 1048576 ))
  498. return
  499. fi
  500. # Linux, in kb
  501. if mem=$(grep MemTotal /proc/meminfo | awk '{ print $2 }'); then
  502. echo $(( ${mem} / 1048576 ))
  503. return
  504. fi
  505. # OS X, in bytes. Note that get_physmem, as used, should only ever
  506. # run in a Linux container (because it's only used in the multiple
  507. # platform case, which is a Dockerized build), but this is provided
  508. # for completeness.
  509. if mem=$(sysctl -n hw.memsize 2>/dev/null); then
  510. echo $(( ${mem} / 1073741824 ))
  511. return
  512. fi
  513. # If we can't infer it, just give up and assume a low memory system
  514. echo 1
  515. }
  516. # Build binaries targets specified
  517. #
  518. # Input:
  519. # $@ - targets and go flags. If no targets are set then all binaries targets
  520. # are built.
  521. # KUBE_BUILD_PLATFORMS - Incoming variable of targets to build for. If unset
  522. # then just the host architecture is built.
  523. kube::golang::build_binaries() {
  524. # Create a sub-shell so that we don't pollute the outer environment
  525. (
  526. # Check for `go` binary and set ${GOPATH}.
  527. kube::golang::setup_env
  528. V=2 kube::log::info "Go version: $(go version)"
  529. local host_platform
  530. host_platform=$(kube::golang::host_platform)
  531. # Use eval to preserve embedded quoted strings.
  532. local goflags goldflags gogcflags
  533. eval "goflags=(${KUBE_GOFLAGS:-})"
  534. goldflags="${KUBE_GOLDFLAGS:-} $(kube::version::ldflags)"
  535. gogcflags="${KUBE_GOGCFLAGS:-}"
  536. local use_go_build
  537. local -a targets=()
  538. local arg
  539. # Add any files with those //generate annotations in the array below.
  540. readonly BINDATAS=( "${KUBE_ROOT}/test/e2e/framework/gobindata_util.go" )
  541. kube::log::status "Generating bindata:" "${BINDATAS[@]}"
  542. for bindata in ${BINDATAS[@]}; do
  543. # Only try to generate bindata if the file exists, since in some cases
  544. # one-off builds of individual directories may exclude some files.
  545. if [[ -f $bindata ]]; then
  546. go generate "${bindata}"
  547. fi
  548. done
  549. for arg; do
  550. if [[ "${arg}" == "--use_go_build" ]]; then
  551. use_go_build=true
  552. elif [[ "${arg}" == -* ]]; then
  553. # Assume arguments starting with a dash are flags to pass to go.
  554. goflags+=("${arg}")
  555. else
  556. targets+=("${arg}")
  557. fi
  558. done
  559. if [[ ${#targets[@]} -eq 0 ]]; then
  560. targets=("${KUBE_ALL_TARGETS[@]}")
  561. fi
  562. local -a platforms=(${KUBE_BUILD_PLATFORMS:-})
  563. if [[ ${#platforms[@]} -eq 0 ]]; then
  564. platforms=("${host_platform}")
  565. fi
  566. local binaries
  567. binaries=($(kube::golang::binaries_from_targets "${targets[@]}"))
  568. local parallel=false
  569. if [[ ${#platforms[@]} -gt 1 ]]; then
  570. local gigs
  571. gigs=$(kube::golang::get_physmem)
  572. if [[ ${gigs} -ge ${KUBE_PARALLEL_BUILD_MEMORY} ]]; then
  573. kube::log::status "Multiple platforms requested and available ${gigs}G >= threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in parallel"
  574. parallel=true
  575. else
  576. kube::log::status "Multiple platforms requested, but available ${gigs}G < threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in serial"
  577. parallel=false
  578. fi
  579. fi
  580. # First build the toolchain before building any other targets
  581. kube::golang::build_kube_toolchain
  582. if [[ "${parallel}" == "true" ]]; then
  583. kube::log::status "Building go targets for {${platforms[*]}} in parallel (output will appear in a burst when complete):" "${targets[@]}"
  584. local platform
  585. for platform in "${platforms[@]}"; do (
  586. kube::golang::set_platform_envs "${platform}"
  587. kube::log::status "${platform}: go build started"
  588. kube::golang::build_binaries_for_platform ${platform} ${use_go_build:-}
  589. kube::log::status "${platform}: go build finished"
  590. ) &> "/tmp//${platform//\//_}.build" &
  591. done
  592. local fails=0
  593. for job in $(jobs -p); do
  594. wait ${job} || let "fails+=1"
  595. done
  596. for platform in "${platforms[@]}"; do
  597. cat "/tmp//${platform//\//_}.build"
  598. done
  599. exit ${fails}
  600. else
  601. for platform in "${platforms[@]}"; do
  602. kube::log::status "Building go targets for ${platform}:" "${targets[@]}"
  603. kube::golang::set_platform_envs "${platform}"
  604. kube::golang::build_binaries_for_platform ${platform} ${use_go_build:-}
  605. done
  606. fi
  607. )
  608. }