You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

buildx.sh 6.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #!/usr/bin/env bash
  2. # Copyright 2021 The KubeEdge 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. set -o errexit
  16. set -o nounset
  17. set -o pipefail
  18. sedna::buildx::prepare_env() {
  19. # Check whether buildx exists.
  20. if ! docker buildx >/dev/null 2>&1; then
  21. echo "ERROR: docker buildx not available. Docker 19.03 or higher is required with experimental features enabled" >&2
  22. exit 1
  23. fi
  24. # Use tonistiigi/binfmt that is to enable an execution of different multi-architecture containers
  25. docker run --privileged --rm tonistiigi/binfmt --install all
  26. # Create a new builder which gives access to the new multi-architecture features.
  27. builder_instance="sedna-buildx"
  28. if ! docker buildx inspect $builder_instance >/dev/null 2>&1; then
  29. docker buildx create --use --name $builder_instance --driver docker-container
  30. fi
  31. docker buildx use $builder_instance
  32. # go speed tag with CGO_ENABLED=1 and alpine image
  33. _speed_buildx_for_cgo_alpine_
  34. }
  35. _speed_buildx_for_go_() {
  36. # docker speed build command for go
  37. echo 'go env -w GOOS="$TARGETOS" GOARCH="$TARGETARCH"' | _feed_to_dockerfile_RUN_command
  38. }
  39. _speed_buildx_for_cgo_alpine_() {
  40. # docker speed build command for go with CGO_ENABLED=1 and alpine image
  41. cat <<'EOF' | _feed_to_dockerfile_RUN_command
  42. # download cc(cross compiler) from https://musl.cc
  43. # the example url: https://musl.cc/aarch64-linux-musl-cross.tgz
  44. apk add curl
  45. # translate some architecture names
  46. arch=$(echo $TARGETARCH | sed "s@arm64@aarch64@")
  47. cc_url=$(curl musl.cc | grep /${arch}-${TARGETOS}-.*-cross)
  48. cc_filename=$(basename $cc_url) # aarch64-linux-musl-cross.tgz
  49. cc_name=$(echo $cc_filename | cut -f1 -d.) # aarch64-linux-musl-cross
  50. # download and extract
  51. curl -O $cc_url; tar xf $cc_filename
  52. # find the real cc name
  53. cc_bin=$PWD/$cc_name/bin # aarch64-linux-musl-cross/bin
  54. export PATH="$cc_bin:$PATH"
  55. # cc=aarch64-linux-musl-cc
  56. # set CC path, and enable CGO
  57. go env -w CC=$(echo $cc_bin/$arch-$TARGETOS-*-cc) CGO_ENABLED=1
  58. go env -w GOOS="$TARGETOS" GOARCH="$TARGETARCH"
  59. EOF
  60. }
  61. _feed_to_dockerfile_RUN_command() {
  62. # add '; \' for each command line
  63. speed_switch_cmd='RUN test "$TARGETPLATFORM" = "$BUILDPLATFORM" || ('
  64. printf "$speed_switch_cmd"
  65. while read run_cmd; do
  66. run_cmd=$(echo "$run_cmd" | sed 's@^\s*@@;s@\s*$@@;') # skip leading/trailing spaces
  67. run_cmd="${run_cmd%# *}" # skip comment
  68. run_cmd="${run_cmd%#;}" # skip trailing ';'
  69. # skip empty command
  70. [ -n "${run_cmd}" ] && {
  71. echo "$run_cmd; \\\\"
  72. }
  73. done
  74. printf ")"
  75. }
  76. sedna::buildx:generate-speed-dockerfile() {
  77. # Add buildx improvement for cross compilation if Dockerfile is added by the specified tag
  78. # see more details for buildx https://github.com/docker/buildx#building-multi-platform-images
  79. local input_dockerfile=${1}
  80. local -a speed_tags=(
  81. # The cross buildx tag in Dockerfile, it should be placed at the line before FROM instruction
  82. # e.g. from build/gm/Dockerfile
  83. # # _speed_buildx_for_go_
  84. # FROM golang:1.14-alpine3.11 AS builder
  85. # go speed tag
  86. _speed_buildx_for_go_
  87. )
  88. local base_cmds='
  89. # These ARGs are built in docker build
  90. # see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
  91. ARG TARGETPLATFORM BUILDPLATFORM TARGETARCH TARGETOS
  92. RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM(=$TARGETOS/$TARGETARCH).."
  93. '
  94. # FROM command pattern
  95. local from_pattern='^\s*FROM\s' # 0+ leading whitespace, 'FROM' word, a whitespace
  96. local from_part='FROM --platform=$BUILDPLATFORM ' # note tailing space
  97. for speed_tag in "${speed_tags[@]}"; do
  98. speed_tag_pattern="^# ${speed_tag}$"
  99. if ! grep -q "$speed_tag_pattern" "$input_dockerfile"; then
  100. continue
  101. fi
  102. speed_cmds="$($speed_tag)"
  103. cross_cmds="
  104. # generated by sedna::buildx
  105. $base_cmds
  106. $speed_cmds
  107. # end generated by sedna::buildx
  108. "
  109. awk -v cross_cmds="$cross_cmds" -v from_part="$from_part" \
  110. "{
  111. if (/$speed_tag_pattern/) {
  112. tag_found = 1
  113. }
  114. if (tag_found && sub(/$from_pattern/, from_part)) {
  115. # add from_part to the FROM command, and print
  116. print
  117. print cross_cmds
  118. tag_found = 0
  119. } else {
  120. print
  121. }
  122. }" "$input_dockerfile"
  123. # only support one language for one Dockerfile
  124. return
  125. done
  126. # if not speed tag added, just output its
  127. cat "$input_dockerfile"
  128. }
  129. sedna::buildx::push-multi-platform-images() {
  130. sedna::buildx::prepare_env
  131. bash scripts/storage-initializer/push_image.sh
  132. for component in ${COMPONENTS[@]}; do
  133. echo "pushing ${PLATFORMS} image for $component"
  134. temp_dockerfile=build/${component}/buildx_dockerfile
  135. sedna::buildx:generate-speed-dockerfile build/${component}/Dockerfile > ${temp_dockerfile}
  136. docker buildx build --push \
  137. --build-arg GO_LDFLAGS=${GO_LDFLAGS} \
  138. --platform ${PLATFORMS} \
  139. -t ${IMAGE_REPO}/sedna-${component}:${IMAGE_TAG} \
  140. -f ${temp_dockerfile} .
  141. rm ${temp_dockerfile}
  142. done
  143. }
  144. sedna::buildx::build-multi-platform-images() {
  145. sedna::buildx::prepare_env
  146. mkdir -p ${OUT_IMAGESPATH}
  147. arch_array=(${PLATFORMS//,/ })
  148. for component in ${COMPONENTS[@]}; do
  149. echo "building ${PLATFORMS} image for ${component}"
  150. buildx_dockerfile=${OUT_IMAGESPATH}/${component}-buildx-Dockerfile
  151. sedna::buildx:generate-speed-dockerfile build/${component}/Dockerfile > ${buildx_dockerfile}
  152. for arch in ${arch_array[@]}; do
  153. dest_tar=${OUT_IMAGESPATH}/${component}-${IMAGE_TAG}-${arch////-}.tar
  154. echo "building ${arch} image for ${component} and the image will be saved in ${dest_tar}"
  155. docker buildx build -o type=docker,dest=${dest_tar} \
  156. --build-arg GO_LDFLAGS=${GO_LDFLAGS} \
  157. --platform ${arch} \
  158. -t ${IMAGE_REPO}/sedna-${component}:${IMAGE_TAG} \
  159. -f ${buildx_dockerfile} .
  160. done
  161. done
  162. }