blob: 2f67c5083720dbda0db6081daf5afe313dbcc527 [file] [log] [blame]
zhangkun83488162d2015-03-25 16:07:50 -07001#!/bin/bash
2
Kun Zhangc8eda8e2015-04-01 16:23:15 -07003# Builds protoc executable into target/protoc.exe
4# To be run from Maven.
5# Usage: build-protoc.sh <OS> <ARCH>
6# <OS> and <ARCH> are ${os.detected.name} and ${os.detected.arch} from os-maven-plugin
7OS=$1
8ARCH=$2
9
Kun Zhangb00a5d72015-04-02 13:14:29 -070010if [[ $# < 2 ]]; then
11 echo "No arguments provided. This script is intended to be run from Maven."
12 exit 1
13fi
14
Kun Zhangc8eda8e2015-04-01 16:23:15 -070015# Under Cygwin, bash doesn't have these in PATH when called from Maven which
16# runs in Windows version of Java.
17export PATH="/bin:/usr/bin:$PATH"
18
19############################################################################
20# Helper functions
21############################################################################
22E_PARAM_ERR=98
23E_ASSERT_FAILED=99
24
Kun Zhangb00a5d72015-04-02 13:14:29 -070025# Usage:
Kun Zhangc8eda8e2015-04-01 16:23:15 -070026fail()
27{
Kun Zhang6f2bc192015-04-07 20:43:20 -070028 echo "ERROR: $1"
29 echo
Kun Zhangc8eda8e2015-04-01 16:23:15 -070030 exit $E_ASSERT_FAILED
31}
32
33# Usage: assertEq VAL1 VAL2 $LINENO
34assertEq ()
35{
36 lineno=$3
37 if [ -z "$lineno" ]; then
38 echo "lineno not given"
39 exit $E_PARAM_ERR
40 fi
41
42 if [[ "$1" != "$2" ]]; then
43 echo "Assertion failed: \"$1\" == \"$2\""
44 echo "File \"$0\", line $lineno" # Give name of file and line number.
45 exit $E_ASSERT_FAILED
46 fi
47}
Kun Zhangb00a5d72015-04-02 13:14:29 -070048
49# Checks the artifact is for the expected architecture
50# Usage: checkArch <path-to-protoc>
51checkArch ()
52{
Kun Zhang6f2bc192015-04-07 20:43:20 -070053 echo
Kun Zhang5c265fa2015-04-07 21:06:37 -070054 echo "Checking file format ..."
Kun Zhangb00a5d72015-04-02 13:14:29 -070055 if [[ "$OS" == windows || "$OS" == linux ]]; then
56 format="$(objdump -f "$1" | grep -o "file format .*$" | grep -o "[^ ]*$")"
Kun Zhang6f2bc192015-04-07 20:43:20 -070057 echo Format=$format
Kun Zhangb00a5d72015-04-02 13:14:29 -070058 if [[ "$OS" == linux ]]; then
59 if [[ "$ARCH" == x86_32 ]]; then
60 assertEq $format "elf32-i386" $LINENO
61 elif [[ "$ARCH" == x86_64 ]]; then
62 assertEq $format "elf64-x86-64" $LINENO
63 else
64 fail "Unsupported arch: $ARCH"
65 fi
66 else
67 # $OS == windows
68 if [[ "$ARCH" == x86_32 ]]; then
69 assertEq $format "pei-i386" $LINENO
70 elif [[ "$ARCH" == x86_64 ]]; then
71 assertEq $format "pei-x86-64" $LINENO
72 else
73 fail "Unsupported arch: $ARCH"
74 fi
75 fi
76 elif [[ "$OS" == osx ]]; then
77 format="$(file -b "$1" | grep -o "[^ ]*$")"
Kun Zhang6f2bc192015-04-07 20:43:20 -070078 echo Format=$format
Kun Zhangc5a2a7c2015-04-06 14:31:29 -070079 if [[ "$ARCH" == x86_32 ]]; then
80 assertEq $format "i386" $LINENO
81 elif [[ "$ARCH" == x86_64 ]]; then
82 assertEq $format "x86_64" $LINENO
83 else
84 fail "Unsupported arch: $ARCH"
85 fi
Kun Zhangb00a5d72015-04-02 13:14:29 -070086 else
Kun Zhang6f2bc192015-04-07 20:43:20 -070087 fail "Unsupported system: $OS"
Kun Zhangb00a5d72015-04-02 13:14:29 -070088 fi
Kun Zhang6f2bc192015-04-07 20:43:20 -070089 echo
90}
91
92# Checks the dependencies of the artifact. Artifacts should only depend on
93# system libraries.
94# Usage: checkDependencies <path-to-protoc>
95checkDependencies ()
96{
97 if [[ "$OS" == windows ]]; then
98 dump_cmd='objdump -x '"$1"' | fgrep "DLL Name"'
99 white_list="KERNEL32\.dll\|msvcrt\.dll"
100 elif [[ "$OS" == linux ]]; then
101 dump_cmd='ldd '"$1"
102 if [[ "$ARCH" == x86_32 ]]; then
103 white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
104 elif [[ "$ARCH" == x86_64 ]]; then
105 white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
106 fi
107 elif [[ "$OS" == osx ]]; then
Kun Zhang5c265fa2015-04-07 21:06:37 -0700108 dump_cmd='otool -L '"$1"' | fgrep dylib'
Kun Zhang62903ec2015-04-08 00:14:36 -0700109 white_list="libz\.1\.dylib\|libstdc++\.6\.dylib\|libSystem\.B\.dylib"
Kun Zhang6f2bc192015-04-07 20:43:20 -0700110 fi
111 if [[ -z "$white_list" || -z "$dump_cmd" ]]; then
112 fail "Unsupported platform $OS-$ARCH."
113 fi
114 echo "Checking for expected dependencies ..."
115 eval $dump_cmd | grep -i "$white_list" || fail "doesn't show any expected dependencies"
116 echo "Checking for unexpected dependencies ..."
117 eval $dump_cmd | grep -i -v "$white_list"
118 ret=$?
119 if [[ $ret == 0 ]]; then
120 fail "found unexpected dependencies (listed above)."
121 elif [[ $ret != 1 ]]; then
122 fail "Error when checking dependencies."
123 fi # grep returns 1 when "not found", which is what we expect
124 echo "Dependencies look good."
125 echo
Kun Zhangb00a5d72015-04-02 13:14:29 -0700126}
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700127############################################################################
128
129echo "Building protoc, OS=$OS ARCH=$ARCH"
130
Kun Zhangb00a5d72015-04-02 13:14:29 -0700131# Nested double quotes are unintuitive, but it works.
132cd "$(dirname "$0")"
133
Kun Zhangae9177d2015-03-31 18:26:28 -0700134WORKING_DIR=$(pwd)
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700135CONFIGURE_ARGS="--disable-shared"
136
137MAKE_TARGET="protoc"
138if [[ "$OS" == windows ]]; then
139 MAKE_TARGET="${MAKE_TARGET}.exe"
140fi
141
Kun Zhangb00a5d72015-04-02 13:14:29 -0700142# Override the default value set in configure.ac that has '-g' which produces
143# huge binary.
144CXXFLAGS="-DNDEBUG"
Kun Zhang6f2bc192015-04-07 20:43:20 -0700145LDFLAGS=""
Kun Zhangb00a5d72015-04-02 13:14:29 -0700146
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700147if [[ "$(uname)" == CYGWIN* ]]; then
148 assertEq "$OS" windows $LINENO
149 # Use mingw32 compilers because executables produced by Cygwin compiler
150 # always have dependency on Cygwin DLL.
151 if [[ "$ARCH" == x86_64 ]]; then
152 CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
153 elif [[ "$ARCH" == x86_32 ]]; then
154 CONFIGURE_ARGS="$CONFIGURE_ARGS --host=i686-pc-mingw32"
155 else
156 fail "Unsupported arch by CYGWIN: $ARCH"
157 fi
158elif [[ "$(uname)" == MINGW32* ]]; then
159 assertEq "$OS" windows $LINENO
160 assertEq "$ARCH" x86_32 $LINENO
Kun Zhang90a7ed62015-04-16 17:30:07 -0700161elif [[ "$(uname)" == MINGW64* ]]; then
162 assertEq "$OS" windows $LINENO
163 assertEq "$ARCH" x86_64 $LINENO
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700164elif [[ "$(uname)" == Linux* ]]; then
Kun Zhang6f2bc192015-04-07 20:43:20 -0700165 if [[ "$OS" == linux ]]; then
166 if [[ "$ARCH" == x86_64 ]]; then
167 CXXFLAGS="$CXXFLAGS -m64"
168 elif [[ "$ARCH" == x86_32 ]]; then
169 CXXFLAGS="$CXXFLAGS -m32"
170 else
171 fail "Unsupported arch: $ARCH"
172 fi
173 elif [[ "$OS" == windows ]]; then
174 # Cross-compilation for Windows
175 # TODO(zhangkun83) MinGW 64 always adds dependency on libwinpthread-1.dll,
176 # which is undesirable for repository deployment.
177 CONFIGURE_ARGS="$CONFIGURE_ARGS"
178 if [[ "$ARCH" == x86_64 ]]; then
179 CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
180 elif [[ "$ARCH" == x86_32 ]]; then
181 CONFIGURE_ARGS="$CONFIGURE_ARGS --host=i686-w64-mingw32"
182 else
183 fail "Unsupported arch: $ARCH"
184 fi
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700185 else
Kun Zhang6f2bc192015-04-07 20:43:20 -0700186 fail "Cannot build $OS on $(uname)"
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700187 fi
188elif [[ "$(uname)" == Darwin* ]]; then
189 assertEq "$OS" osx $LINENO
Kun Zhang62903ec2015-04-08 00:14:36 -0700190 # Make the binary compatible with OSX 10.7 and later
191 CXXFLAGS="$CXXFLAGS -mmacosx-version-min=10.7"
Kun Zhangc5a2a7c2015-04-06 14:31:29 -0700192 if [[ "$ARCH" == x86_64 ]]; then
193 CXXFLAGS="$CXXFLAGS -m64"
194 elif [[ "$ARCH" == x86_32 ]]; then
195 CXXFLAGS="$CXXFLAGS -m32"
196 else
197 fail "Unsupported arch: $ARCH"
198 fi
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700199else
200 fail "Unsupported system: $(uname)"
201fi
Kun Zhangae9177d2015-03-31 18:26:28 -0700202
Kun Zhange4f1f932015-03-31 16:28:57 -0700203# Statically link libgcc and libstdc++.
Kun Zhang87b85012015-04-01 18:02:36 -0700204# -s to produce stripped binary.
205# And they don't work under Mac.
206if [[ "$OS" != osx ]]; then
Kun Zhang6f2bc192015-04-07 20:43:20 -0700207 LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -s"
Kun Zhang87b85012015-04-01 18:02:36 -0700208fi
Kun Zhang36093ca2015-03-31 22:07:13 +0100209
Kun Zhang6f2bc192015-04-07 20:43:20 -0700210export CXXFLAGS LDFLAGS
211
Kun Zhangb00a5d72015-04-02 13:14:29 -0700212TARGET_FILE=target/protoc.exe
213
Kun Zhangc8eda8e2015-04-01 16:23:15 -0700214cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS &&
Kun Zhang90a7ed62015-04-16 17:30:07 -0700215 cd src && make clean && make google/protobuf/stubs/pbconfig.h $MAKE_TARGET &&
Kun Zhangae9177d2015-03-31 18:26:28 -0700216 cd "$WORKING_DIR" && mkdir -p target &&
Kun Zhang1c126122015-04-08 10:39:21 -0700217 (cp ../src/protoc $TARGET_FILE || cp ../src/protoc.exe $TARGET_FILE) ||
218 exit 1
219
220if [[ "$OS" == osx ]]; then
221 # Since Mac linker doesn't accept "-s", we need to run strip
222 strip $TARGET_FILE || exit 1
223fi
224
225checkArch $TARGET_FILE && checkDependencies $TARGET_FILE