forked from awslabs/aws-lambda-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackager
executable file
·191 lines (166 loc) · 5.43 KB
/
packager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
# Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
set -euo pipefail
print_help() {
echo -e "Usage: packager [OPTIONS] <binary name>\n"
echo -e "OPTIONS\n"
echo -e "\t-d,--default-libc\t Use the target host libc libraries. This will not package the C library files.\n"
}
if [ $# -lt 1 ]; then
echo -e "Error: missing arguments\n"
print_help
exit 1
fi
POSITIONAL=()
INCLUDE_LIBC=true
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-d|--default-libc)
INCLUDE_LIBC=false
shift # past argument
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
PKG_BIN_PATH=$1
if [ ! -f "$PKG_BIN_PATH" ]; then
echo "$PKG_BIN_PATH" - No such file.;
exit 1;
fi
if ! type zip > /dev/null 2>&1; then
echo "zip utility is not found. Please install it and re-run this script"
exit 1
fi
function find_so_files() {
sed -E '/\.so$|\.so\.[0-9]+$/!d'
}
function package_libc_alpine() {
# -F matches a fixed string rather than a regex (grep that comes with busybox doesn't know --fixed-strings)
if grep -F "Alpine Linux" < /etc/os-release > /dev/null; then
if type apk > /dev/null 2>&1; then
apk info --contents musl 2>/dev/null | find_so_files | sed 's/^/\//'
fi
fi
}
function package_libc_pacman() {
if grep --extended-regexp "Arch Linux|Manjaro Linux" < /etc/os-release > /dev/null 2>&1; then
if type pacman > /dev/null 2>&1; then
pacman --query --list --quiet glibc | find_so_files
fi
fi
}
function package_libc_dpkg() {
if type dpkg-query > /dev/null 2>&1; then
dpkg-query --listfiles libc6:$(dpkg --print-architecture) | find_so_files
fi
}
function package_libc_rpm() {
if type rpm > /dev/null 2>&1; then
rpm --query --list glibc.$(uname -m) | find_so_files
fi
}
# hasElement expects an element and an array parameter
# it's equivalent to array.contains(element)
# e.g. hasElement "needle" ${haystack[@]}
function hasElement() {
local el key=$1
shift
for el in "$@"
do
[[ "$el" == "$key" ]] && return 0
done
return 1
}
PKG_BIN_FILENAME=$(basename "$PKG_BIN_PATH")
PKG_DIR=tmp
PKG_LD=""
list=$(ldd "$PKG_BIN_PATH" | awk '{print $(NF-1)}')
libc_libs=()
libc_libs+=($(package_libc_dpkg))
libc_libs+=($(package_libc_rpm))
libc_libs+=($(package_libc_pacman))
libc_libs+=($(package_libc_alpine))
mkdir -p "$PKG_DIR/bin" "$PKG_DIR/lib"
for i in $list
do
if [[ ! -f $i ]]; then # ignore linux-vdso.so.1
continue
fi
# Do not copy libc files which are directly linked unless it's the dynamic loader
if hasElement "$i" "${libc_libs[@]}"; then
filename=$(basename "$i")
if [[ -z "${filename##ld-*}" ]]; then
PKG_LD=$filename # Use this file as the loader
cp "$i" "$PKG_DIR/lib"
fi
continue
fi
cp "$i" $PKG_DIR/lib
done
if [[ $INCLUDE_LIBC == true ]]; then
for i in "${libc_libs[@]}"
do
filename=$(basename "$i")
if [[ -z "${filename##ld-*}" ]]; then
# if the loader is empty, then the binary is probably linked to a symlink of the loader. The symlink will
# not show up when quering the package manager for libc files. So, in this case, we want to copy the loader
if [[ -z "$PKG_LD" ]]; then
PKG_LD=$filename
cp "$i" "$PKG_DIR/lib" # we want to follow the symlink (default behavior)
fi
continue # We don't want the dynamic loader's symlink because its target is an absolute path (/lib/ld-*).
fi
cp --no-dereference "$i" "$PKG_DIR/lib"
done
fi
if [[ -z "$PKG_LD" ]]; then
echo "Failed to identify, locate or package the loader. Please file an issue on Github!" 1>&2
exit 1
fi
bootstrap_script=$(cat <<EOF
#!/bin/bash
set -euo pipefail
export AWS_EXECUTION_ENV=lambda-cpp
exec \$LAMBDA_TASK_ROOT/lib/$PKG_LD --library-path \$LAMBDA_TASK_ROOT/lib \$LAMBDA_TASK_ROOT/bin/$PKG_BIN_FILENAME \${_HANDLER}
EOF
)
bootstrap_script_no_libc=$(cat <<EOF
#!/bin/bash
set -euo pipefail
export AWS_EXECUTION_ENV=lambda-cpp
export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$LAMBDA_TASK_ROOT/lib
exec \$LAMBDA_TASK_ROOT/bin/$PKG_BIN_FILENAME \${_HANDLER}
EOF
)
cp "$PKG_BIN_PATH" "$PKG_DIR/bin"
if [[ $INCLUDE_LIBC == true ]]; then
echo -e "$bootstrap_script" > "$PKG_DIR/bootstrap"
else
echo -e "$bootstrap_script_no_libc" > "$PKG_DIR/bootstrap"
fi
chmod +x "$PKG_DIR/bootstrap"
# some shenanigans to create the right layout in the zip file without extraneous directories
pushd "$PKG_DIR" > /dev/null
zip --symlinks --recurse-paths "$PKG_BIN_FILENAME".zip -- *
ORIGIN_DIR=$(dirs -l +1)
mv "$PKG_BIN_FILENAME".zip "$ORIGIN_DIR"
popd > /dev/null
rm -r "$PKG_DIR"
echo Created "$ORIGIN_DIR/$PKG_BIN_FILENAME".zip