make.bash 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #!/usr/bin/env bash
  2. # -x echos commands.
  3. # -e exits if a command returns an error.
  4. set -x -e
  5. if [ ! -f make.bash ]; then
  6. echo "make.bash must be run from $GOPATH/src/github.com/Psiphon-Labs/psiphon-tunnel-core/ClientLibrary"
  7. exit 1
  8. fi
  9. # This script takes an optional second argument: 'private', if private plugins should
  10. # be used. It should be omitted if private plugins are not desired.
  11. if [[ $2 == "private" ]]; then
  12. FORCE_PRIVATE_PLUGINS=true
  13. echo "TRUE"
  14. else
  15. FORCE_PRIVATE_PLUGINS=false
  16. echo "FALSE"
  17. fi
  18. # BUILD_TAGS needs to be outside of prepare_build because it determines what's fetched by go-get.
  19. PRIVATE_PLUGINS_TAG=""
  20. if [[ ${FORCE_PRIVATE_PLUGINS} == true ]]; then PRIVATE_PLUGINS_TAG="PRIVATE_PLUGINS"; fi
  21. BUILD_TAGS="${PRIVATE_PLUGINS_TAG}"
  22. WINDOWS_BUILD_TAGS="${BUILD_TAGS}"
  23. LINUX_BUILD_TAGS="${BUILD_TAGS}"
  24. ANDROID_BUILD_TAGS="${BUILD_TAGS}"
  25. BUILD_DIR=build
  26. if [ ! -d ${BUILD_DIR} ]; then
  27. mkdir ${BUILD_DIR}
  28. fi
  29. prepare_build () {
  30. BUILDDATE=$(date --iso-8601=seconds)
  31. BUILDREPO=$(git config --get remote.origin.url)
  32. BUILDREV=$(git rev-parse --short HEAD)
  33. GOVERSION=$(go version | perl -ne '/go version (.*?) / && print $1')
  34. # - starts the string with a `{`
  35. # - uses the `go list` command and passes it a template string (using the Go template syntax) saying I want all the dependencies of the package in the current directory, printing 1/line via printf
  36. # - pipes to `xargs` to run a command on each line output from the first command
  37. # - uses `go list` with a template string to print the "Import Path" (from just below `$GOPATH/src`) if the package is not part of the standard library
  38. # - pipes to `xargs` again, specifiying `pkg` as the placeholder name for each item being operated on (which is the list of non standard library import paths from the previous step)
  39. # - `xargs` runs a bash script (via `-c`) which changes to each import path in sequence, then echoes out `"<import path>":"<subshell output of getting the short git revision>",`
  40. # - this leaves a trailing `,` at the end, and no close to the JSON object, so simply `sed` replace the comma before the end of the line with `}` and you now have valid JSON
  41. DEPENDENCIES=$(echo -n "{" && go list -tags "$1" -f '{{range $dep := .Deps}}{{printf "%s\n" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | xargs -I pkg bash -c 'cd $GOPATH/src/pkg && echo -n "\"pkg\":\"$(git rev-parse --short HEAD)\","' | sed 's/,$/}/')
  42. LDFLAGS="\
  43. -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
  44. -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
  45. -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
  46. -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
  47. -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
  48. "
  49. echo "Variables for ldflags:"
  50. echo " Build date: ${BUILDDATE}"
  51. echo " Build repo: ${BUILDREPO}"
  52. echo " Build revision: ${BUILDREV}"
  53. echo " Go version: ${GOVERSION}"
  54. echo " Dependencies: ${DEPENDENCIES}"
  55. echo ""
  56. }
  57. build_for_android () {
  58. TARGET_OS=android
  59. OUTPUT_DIR="${BUILD_DIR}/${TARGET_OS}"
  60. echo "...Getting project dependencies (via go get) for Android."
  61. GOOS=windows go get -d -v -tags "$ANDROID_BUILD_TAGS" ./...
  62. prepare_build "$ANDROID_BUILD_TAGS"
  63. if [ $? != 0 ]; then
  64. echo "....'go get' failed, exiting"
  65. exit $?
  66. fi
  67. TARGET_NDK=android-ndk-r17b
  68. curl https://dl.google.com/android/repository/${TARGET_NDK}-linux-x86_64.zip -o ~/android-ndk.zip
  69. unzip ~/android-ndk.zip -d ~/
  70. NDK_TOOLCHAIN_DIR=~/android-ndk-toolchain
  71. mkdir -p ${NDK_TOOLCHAIN_DIR}
  72. TARGET_ARCH=arm
  73. ARMV=7
  74. ~/${TARGET_NDK}/build/tools/make_standalone_toolchain.py --arch "${TARGET_ARCH}" --install-dir "${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}"
  75. CC="${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}/bin/arm-linux-androideabi-clang" \
  76. CXX="${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}/bin/arm-linux-androideabi-clang++" \
  77. GOARM=${ARMV} \
  78. GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$ANDROID_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}${ARMV}.so" PsiphonTunnel.go
  79. TARGET_ARCH=arm64
  80. ~/${TARGET_NDK}/build/tools/make_standalone_toolchain.py --arch "${TARGET_ARCH}" --install-dir "${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}"
  81. CC="${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}/bin/aarch64-linux-android-clang" \
  82. CXX="${NDK_TOOLCHAIN_DIR}/${TARGET_ARCH}/bin/aarch64-linux-android-clang++" \
  83. GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$ANDROID_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}.so" PsiphonTunnel.go
  84. }
  85. build_for_linux () {
  86. TARGET_OS=linux
  87. OUTPUT_DIR="${BUILD_DIR}/${TARGET_OS}"
  88. echo "...Getting project dependencies (via go get) for Linux."
  89. GOOS=linux go get -d -v -tags "$LINUX_BUILD_TAGS" ./...
  90. prepare_build "$LINUX_BUILD_TAGS"
  91. if [ $? != 0 ]; then
  92. echo "....'go get' failed, exiting"
  93. exit $?
  94. fi
  95. TARGET_ARCH=386
  96. # TODO: is "CFLAGS=-m32" required?
  97. CFLAGS=-m32 \
  98. GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$LINUX_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}.so" PsiphonTunnel.go
  99. TARGET_ARCH=amd64
  100. GOOS=linux GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$LINUX_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}.so" PsiphonTunnel.go
  101. }
  102. build_for_windows () {
  103. TARGET_OS=windows
  104. OUTPUT_DIR="${BUILD_DIR}/${TARGET_OS}"
  105. echo "...Getting project dependencies (via go get) for Windows."
  106. GOOS=windows go get -d -v -tags "$WINDOWS_BUILD_TAGS" ./...
  107. prepare_build "$WINDOWS_BUILD_TAGS"
  108. if [ $? != 0 ]; then
  109. echo "....'go get' failed, exiting"
  110. exit $?
  111. fi
  112. TARGET_ARCH=386
  113. CGO_ENABLED=1 \
  114. CGO_LDFLAGS="-L /usr/i686-w64-mingw32/lib/ -lwsock32 -lcrypt32 -lgdi32" \
  115. CC=/usr/bin/i686-w64-mingw32-gcc \
  116. GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$WINDOWS_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}.dll" PsiphonTunnel.go
  117. TARGET_ARCH=amd64
  118. CGO_ENABLED=1 \
  119. CGO_LDFLAGS="-L /usr/x86_64-w64-mingw32/lib/ -lwsock32 -lcrypt32 -lgdi32" \
  120. CC=/usr/bin/x86_64-w64-mingw32-gcc \
  121. GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build -buildmode=c-shared -ldflags "$LDFLAGS" -tags "$WINDOWS_BUILD_TAGS" -o "${OUTPUT_DIR}/PsiphonTunnel-${TARGET_OS}-${TARGET_ARCH}.dll" PsiphonTunnel.go
  122. }
  123. build_for_ios () {
  124. echo "To build for iOS please use build-darwin.sh"
  125. }
  126. build_for_macos () {
  127. echo "To build for macos please use build-darwin.sh"
  128. }
  129. TARGET=$1
  130. case $TARGET in
  131. windows)
  132. echo "..Building for Windows"
  133. build_for_windows $2
  134. exit $?
  135. ;;
  136. linux)
  137. echo "..Building for Linux"
  138. build_for_linux $2
  139. exit $?
  140. ;;
  141. macos)
  142. echo "..Building for MacOS"
  143. build_for_macos
  144. exit $?
  145. ;;
  146. android)
  147. echo "..Building for Android"
  148. build_for_android
  149. exit $?
  150. ;;
  151. ios)
  152. echo "..Building for iOS"
  153. build_for_ios
  154. exit $?
  155. ;;
  156. all)
  157. echo "..Building all"
  158. build_for_windows $2
  159. if [ $? != 0 ]; then
  160. exit $?
  161. fi
  162. build_for_linux $2
  163. if [ $? != 0 ]; then
  164. exit $?
  165. fi
  166. build_for_macos
  167. if [ $? != 0 ]; then
  168. exit $?
  169. fi
  170. build_for_android
  171. if [ $? != 0 ]; then
  172. exit $?
  173. fi
  174. build_for_ios
  175. if [ $? != 0 ]; then
  176. exit $?
  177. fi
  178. ;;
  179. *)
  180. echo "..No selection made, building all"
  181. build_for_windows $2
  182. if [ $? != 0 ]; then
  183. exit $?
  184. fi
  185. build_for_linux $2
  186. if [ $? != 0 ]; then
  187. exit $?
  188. fi
  189. build_for_macos
  190. if [ $? != 0 ]; then
  191. exit $?
  192. fi
  193. build_for_android
  194. if [ $? != 0 ]; then
  195. exit $?
  196. fi
  197. build_for_ios
  198. if [ $? != 0 ]; then
  199. exit $?
  200. fi
  201. ;;
  202. esac
  203. echo "BUILD DONE"