TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / packaging / macosx / osx-app.sh.in
blobc484a5da7657f160944c5784e0211184dab506e2
1 #!/bin/bash
3 # USAGE
4 # osx-app [-s] [-l /path/to/libraries]
6 # This script attempts to build an application bundle for macOS, resolving
7 # dynamic libraries, etc.
8 # It strips the executable and libraries if '-s' is given.
10 # AUTHORS
11 # Kees Cook <kees@outflux.net>
12 # Michael Wybrow <mjwybrow@users.sourceforge.net>
13 # Jean-Olivier Irisson <jo.irisson@gmail.com>
15 # Copyright (C) 2005 Kees Cook
16 # Copyright (C) 2005-2007 Michael Wybrow
17 # Copyright (C) 2007 Jean-Olivier Irisson
19 # Released under GNU GPL, read the file 'COPYING' for more information
21 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
22 # https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
24 # NB:
25 # This originally came from Inkscape; Inkscape's configure script has an
26 # "--enable-osxapp", which causes some of Inkscape's installation data
27 # files to have macOS-ish paths under Contents/Resources of the bundle
28 # or under /Library/Application Support. We don't have such an option;
29 # we just put them in "bin", "etc", "lib", and "share" directories
30 # under Contents/Resources, rather than in the "bin", "etc", "lib",
31 # and "share" directories under the installation directory.
34 # XXX We could probably replace a lot of this with https://github.com/auriamg/macdylibbundler
36 shopt -s extglob
38 # Defaults
39 strip=false
40 install_exclude_prefixes="/System/|/Library/|/usr/lib/|/usr/X11/|/opt/X11/|@executable_path"
42 # Bundle always has the same name. Version information is stored in
43 # the Info.plist file which is filled in by the configure script.
44 bundle="Wireshark.app"
46 # Location for libraries (tools/macos-setup.sh defaults to whatever the
47 # various support libraries use as their standard installation location,
48 # which is /usr/local)
49 if [ -z "$LIBPREFIX" ]; then
50 LIBPREFIX="/usr/local"
54 # Help message
55 #----------------------------------------------------------
56 help()
58 echo -e "
59 Create an app bundle for macOS
61 USAGE
62 $0 [-s] [-l /path/to/libraries]
64 OPTIONS
65 -h,--help
66 Display this help message.
67 -b,--bundle
68 The application bundle name. Default is Wireshark.app.
70 Strip the libraries and executables from debugging symbols.
71 -l,--libraries
72 Specify the path to the libraries the application depends
73 on (typically /sw or /opt/local). By default it is
74 /usr/local.
76 EXAMPLE
77 $0 -b Stratoshark.app -s -l /opt/local
82 # Parse command line arguments
83 #----------------------------------------------------------
84 while [ "$1" != "" ]
86 case $1 in
87 -b|--bundle)
88 bundle="$2"
89 shift 1 ;;
90 -s)
91 strip=true ;;
92 -l|--libraries)
93 LIBPREFIX="$2"
94 shift 1 ;;
95 -h|--help)
96 help
97 exit 0 ;;
99 echo "Invalid command line option: $1"
100 exit 2 ;;
101 esac
102 shift 1
103 done
105 # Safety tests
106 if [ ! -e "$LIBPREFIX" ]; then
107 echo "Cannot find the directory containing the libraries: $LIBPREFIX" >&2
108 exit 1
111 if [ ! -d "$bundle" ] ; then
112 echo "$bundle not found" >&2
113 exit 1
116 qt_frameworks_dir=$( "@QT_QMAKE_EXECUTABLE@" -query QT_INSTALL_LIBS )
117 if [ ! -d "$qt_frameworks_dir" ] ; then
118 echo "Can't find the Qt frameworks directory" >&2
119 exit 1
122 sparkle_version="@SPARKLE_VERSION@"
123 sparkle_frameworks_dir="@SPARKLE_LIBRARY@"
126 # Define the signing identities, or use self-signed ("-")
127 # if the identity is not provided.
128 if [ -n "$CODE_SIGN_IDENTITY" ] ; then
129 codesign_dev_app_identity="Developer ID Application: $CODE_SIGN_IDENTITY"
130 codesign_dev_install_identity="Developer ID Installer: $CODE_SIGN_IDENTITY"
131 else
132 codesign_dev_app_identity="-"
133 codesign_dev_install_identity="-"
137 # Leave the Qt frameworks out of the special processing.
139 install_exclude_prefixes="$install_exclude_prefixes|$qt_frameworks_dir"
141 app_name=${bundle%%.app}
142 app_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
144 # Package paths
145 pkgexec="$bundle/Contents/MacOS"
146 #pkgres="$bundle/Contents/Resources"
147 pkglib="$bundle/Contents/Frameworks"
148 pkgplugin="$bundle/Contents/PlugIns/$app_lower/@PLUGIN_PATH_ID@"
150 # Set the 'macosx' directory, usually the current directory.
151 #resdir=$( pwd )
154 # Get a list of all binaries in the bundle.
155 # Treat all plain files with read and execute permissions for all as
156 # binaries.
158 secondary_binary_list=()
159 while read -r binary ; do
160 secondary_binary_list+=("$binary")
161 done < <( find "$pkgexec" \! -name "$app_name" -type f -perm -0555 -print | sort )
162 plugin_library_list=()
163 while read -r library ; do
164 plugin_library_list+=("$library")
165 done < <( find "$pkgplugin" -name "*.so" -type f -perm -0555 -print | sort )
166 bundle_binary_list=("$pkgexec/$app_name" "${secondary_binary_list[@]}" "${plugin_library_list[@]}")
168 echo -e "\\nFixing up $bundle..."
170 # Start with a clean Frameworks slate.
171 if [ -d "$pkglib" ] ; then
172 printf "Removing %s\n" "$pkglib"
173 rm -v -r -f "$pkglib"
175 mkdir -v -m u=rwx,go=rx "$pkglib"
177 echo -e "\\nPrepopulating our libraries"
179 # Copy only <library>.<SOVERSION>.dylib.
180 cp -v +([^.]).+([[:digit:]]).dylib "$pkglib"
182 # Fetch a unique list of LC_RPATHs from our executables, which will be used
183 # for our dependency search below.
184 bundle_binary_rpaths=("/usr/local/lib")
185 rpaths=()
187 # macdeployqt handles our Qt dependencies. We handle our Sparkle and
188 # internal dependencies.
189 skip_pats="Qt|Sparkle|build/run"
191 for binary in "${bundle_binary_list[@]}" "$pkglib"/*.dylib ; do
192 while read -r rpath ; do
193 bundle_binary_rpaths+=("$rpath")
194 done < <( otool -l "$binary" | grep -A2 LC_RPATH | awk '$1=="path" && $2 !~ /^@/ {print $2}' | grep -E -v "$skip_pats" )
195 done
197 while read -r rpath ; do
198 rpaths+=("$rpath")
199 done < <( printf '%s\n' "${bundle_binary_rpaths[@]}" | sort -u)
201 printf "\nSearching the following LC_RPATHs for dependencies:\n"
202 printf '%s\n' "${rpaths[@]}"
204 # Find out libs we need from Fink, MacPorts, or from a custom install
205 # (i.e. $LIBPREFIX), then loop until no changes.
207 nfiles=0
208 endl=true
209 while $endl; do
210 echo -e "\\nLooking for dependencies. Round $a"
212 # To find dependencies, we:
214 # run otool -L on all the binaries in the bundle, and on all
215 # the shared libraries in the $pkglib directory, to find all
216 # the libraries they depend on (we don't bother with the
217 # frameworks, as the only frameworks we ship are the Qt
218 # frameworks, which don't depend on any libraries that
219 # don't ship with the OS, and as it's hard to find the
220 # framework libraries under $pkglib without getting
221 # non-framework files);
223 # filter out all lines that don't contain "compatibility" to
224 # remove lines of output that don't correspond to dependencies;
226 # use cut to extract the library name from the output;
228 # replace "\tlibbrotli" with "\t/usr/local/lib/libbrotli" so that
229 # it isn't excluded from subsequent filtering.
230 # libbrotli 1.09 and earlier doesn't have a path prefix in its
231 # "install name" when built by tools/macos-setup.sh:
232 # https://github.com/google/brotli/pull/976;
234 # replace "@loader_path/libbrotli" with "/usr/local/lib/libbrotli" so that
235 # it isn't excluded from subsequent filtering;
237 # strip out system libraries, as we don't bundle them with
238 # Wireshark;
240 # eliminate duplicates.
242 # We might want to let dyld do some of the work for us, e.g. by
243 # parsing the output of
245 # `DYLD_PRINT_LIBRARIES=1 $bundle_binary`
247 # instead, or just use CMake's fixup_bundle:
248 # https://cmake.org/cmake/help/latest/module/BundleUtilities.html
249 libs=()
250 while read -r lib ; do
251 libs+=("$lib")
252 done < <(
253 otool -L "${bundle_binary_list[@]}" "$pkglib"/*.dylib 2>/dev/null \
254 | grep -F compatibility \
255 | grep -v @rpath \
256 | cut -d\( -f1 \
257 | sed '1,$s;^ libbrotli; /usr/local/lib/libbrotli;' \
258 | sed '1,$s;^ @loader_path/libbrotli; /usr/local/lib/libbrotli;' \
259 | grep -E -v "$install_exclude_prefixes" \
260 | sort \
261 | uniq \
263 while read -r rpath_lib _ ; do
264 suffix=${rpath_lib/@rpath\/}
265 for rpath in "${rpaths[@]}" ; do
266 if [ -f "$rpath/$suffix" ] ; then
267 printf "Found @rpath/%s in %s\n" "$suffix" "$rpath"
268 libs+=("$rpath/$suffix")
270 done
271 done < <( otool -L "${bundle_binary_list[@]}" "$pkglib"/*.dylib \
272 | grep @rpath \
273 | grep -E -v "$skip_pats" \
274 | sort -u \
276 install -m 644 -C -v "${libs[@]}" "$pkglib"
277 (( a++ ))
278 # shellcheck disable=SC2012
279 nnfiles=$( ls "$pkglib" | wc -l )
280 if (( nnfiles == nfiles )); then
281 endl=false
282 else
283 nfiles=$nnfiles
285 done
287 # Strip libraries and executables if requested
288 #----------------------------------------------------------
289 if [ "$strip" = "true" ]; then
290 echo -e "\\nStripping debugging symbols...\\n"
291 strip -x "$pkglib"/*.dylib
292 strip -ur "${bundle_binary_list[@]}"
295 "@QT_MACDEPLOYQT_EXECUTABLE@" "$bundle" -no-strip -verbose=2 || exit 1
298 # The build process added to the Wireshark/Stratoshark binary an rpath
299 # entry pointing to the directory containing the Qt frameworks; remove
300 # that entry from the binary in the package.
302 /usr/bin/install_name_tool -delete_rpath "$qt_frameworks_dir" "$pkgexec/$app_name"
304 if [ -d "$sparkle_frameworks_dir" ] ; then
305 cp -R "$sparkle_frameworks_dir" "$pkglib" || exit 1
306 # Remove these if we ever start sandboxing.
307 rm -f "$pkglib/Sparkle.framework/XPCServices" || exit 1
308 rm -rf "$pkglib/Sparkle.framework/Versions/B/XPCServices" || exit 1
311 # NOTE: we must rpathify *all* files, *including* Qt libraries etc.,
313 rpathify_file () {
314 local rpathify_exclude_prefixes="$install_exclude_prefixes|@rpath"
316 # Fix a given executable, library, or plugin to be relocatable
317 if [ ! -f "$1" ]; then
318 return 0;
322 # OK, what type of file is this?
324 if ! filetype=$( otool -hv "$1" | grep -E MH_MAGIC | awk '{print $5}' ; exit "${PIPESTATUS[0]}" ) ; then
325 echo "Unable to rpathify $1 in $( pwd ): file type failed."
326 exit 1
329 case "$filetype" in
331 EXECUTE|DYLIB|BUNDLE)
333 # Executable, library, or plugin. (Plugins
334 # can be either DYLIB or BUNDLE; shared
335 # libraries are DYLIB.)
337 # For DYLIB and BUNDLE, fix the shared
338 # library identification.
340 if [[ "$filetype" = "DYLIB" || "$filetype" = "BUNDLE" ]]; then
341 echo "Changing shared library identification of $1"
342 base=$( echo "$1" | awk -F/ '{print $NF}' )
344 # The library will end up in a directory in
345 # the rpath; this is what we should change its
346 # ID to.
348 to=@rpath/$base
349 /usr/bin/install_name_tool -id "$to" "$1"
352 # If we're a library and we depend on something in
353 # @executable_path/../Frameworks, replace that with
354 # @rpath.
356 while read -r dep_lib ; do
357 base=$( echo "$dep_lib" | awk -F/ '{print $NF}' )
358 to="@rpath/$base"
359 echo "Changing reference to $dep_lib to $to in $1"
360 /usr/bin/install_name_tool -change "$dep_lib" "$to" "$1"
361 done < <( otool -L "$1" | grep @executable_path/../Frameworks | awk '{print $1}' )
364 # Try to work around brotli's lack of a full path
365 # https://github.com/google/brotli/issues/934
367 while read -r base ; do
368 to="@rpath/$base"
369 echo "Changing reference to $base to $to in $1"
370 /usr/bin/install_name_tool -change "$base" "$to" "$1"
371 done < <( otool -L "$1" | grep '^ libbrotli' | awk '{print $1}' )
375 # Find our local rpaths and remove them.
377 otool -l "$1" | grep -A2 LC_RPATH \
378 | awk '$1=="path" && $2 !~ /^@/ {print $2}' \
379 | grep -E -v "$rpathify_exclude_prefixes" | \
380 while read -r lc_rpath ; do
381 echo "Stripping LC_RPATH $lc_rpath from $1"
382 install_name_tool -delete_rpath "$lc_rpath" "$1"
383 done
386 # Add -Wl,-rpath,@executable_path/../Frameworks
387 # to the rpath, so it'll find the bundled
388 # frameworks and libraries if they're referred
389 # to by @rpath/, rather than having a wrapper
390 # script tweak DYLD_LIBRARY_PATH.
392 if [[ "$filetype" = "EXECUTE" ]]; then
393 if [ -d ../Frameworks ] ; then
394 framework_path=../Frameworks
395 elif [ -d ../../Frameworks ] ; then
396 framework_path=../../Frameworks
397 else
398 echo "Unable to find relative path to Frameworks for $1 from $( pwd )"
399 exit 1
402 echo "Adding @executable_path/$framework_path to rpath of $1"
403 /usr/bin/install_name_tool -add_rpath @executable_path/$framework_path "$1"
407 # Show the minimum supported version of macOS
408 # for each executable or library
410 if [[ "$filetype" = "EXECUTE" || "$filetype" = "DYLIB" ]] ; then
411 echo "Minimum macOS version for $1:"
412 otool -l "$1" | grep -A3 LC_VERSION_MIN_MACOSX
416 # Get the list of dynamic libraries on which this
417 # file depends, and select only the libraries that
418 # are in $LIBPREFIX, as those are the only ones
419 # that we'll be shipping in the app bundle; the
420 # other libraries are system-supplied or supplied
421 # as part of X11, will be expected to be on the
422 # system on which the bundle will be installed,
423 # and should be referred to by their full pathnames.
425 local libs=()
426 while read -r lib ; do
427 libs+=("$lib")
428 done < <( otool -L "$1" \
429 | grep -F compatibility \
430 | cut -d\( -f1 \
431 | grep -E -v "$rpathify_exclude_prefixes" \
432 | sort \
433 | uniq \
436 for lib in "${libs[@]}"; do
438 # Get the file name of the library.
440 base=$( echo "$lib" | awk -F/ '{print $NF}' )
442 # The library will end up in a directory in
443 # the rpath; this is what we should change its
444 # file name to.
446 to=@rpath/$base
448 # Change the reference to that library.
450 echo "Changing reference to $lib to $to in $1"
451 /usr/bin/install_name_tool -change "$lib" "$to" "$1"
452 done
454 esac
457 rpathify_dir () {
459 # Make sure we *have* that directory
461 if [ -d "$1" ]; then
462 (cd "$1" || exit 1
463 echo "rpathifying $1"
465 # Make sure we *have* files to fix
467 # shellcheck disable=SC2086
468 files=$( ls $2 2>/dev/null )
469 if [ -n "$files" ]; then
470 for file in $files; do
471 rpathify_file "$file" "$( pwd )"
472 done
473 else
474 echo "no files found in $1"
477 rf_ret=$?
478 if [ $rf_ret -ne 0 ] ; then exit $rf_ret ; fi
482 rpathify_files () {
484 # Fix bundle deps
486 rpathify_dir "$pkglib" "*.dylib"
487 rpathify_dir "$pkgexec" "*"
488 for plugindir in "$pkgplugin"/*
490 rpathify_dir "$plugindir" "*"
491 done
493 rpathify_dir "$pkgexec/extcap" "*"
496 if [ ${#LIBPREFIX} -ge "6" ]; then
497 # If the LIBPREFIX path is long enough to allow
498 # path rewriting, then do this.
499 # 6 is the length of @rpath, which replaces LIBPREFIX.
500 rpathify_files
501 else
502 echo "Could not rewrite dylib paths for bundled libraries. This requires" >&2
503 echo "the support libraries to be installed in a PREFIX of at least 6 characters in length." >&2
504 echo "" >&2
505 exit 1
509 # QtNetwork might be linked with brotli.
510 rpathify_file "$pkglib/QtNetwork.framework/Versions/Current/QtNetwork"
512 bundle_dsym="${bundle%%.app}.dSYM"
514 frameworks=()
515 for framework in "$pkglib"/*.framework/Versions/*/* ; do
516 if [ -f "$framework" ];then
517 frameworks+=("$framework")
519 done
521 echo "Dsymifying binaries to $bundle_dsym:"
522 # shellcheck disable=SC2086
523 dsymutil --minimize --out "$bundle_dsym" \
524 "${bundle_binary_list[@]}" \
525 "${frameworks[@]}" \
526 "$pkglib"/*.dylib
528 # echo "Stripping binaries:"
529 # # shellcheck disable=SC2086
530 # strip -S \
531 # "${bundle_binary_list[@]}" \
532 # "${frameworks[@]}" \
533 # "$pkglib"/*.dylib \
534 # "$pkgplugin"/*/*.so
536 # XXX What's the proper directory layout here?
537 # dsymify_file () {
538 # # out_dsym="${1/#$bundle/$bundle_dsym}.dSYM"
539 # echo " $1"
540 # dsymutil --minimize --out "$bundle_dsym" "$1"
541 # strip "$1"
544 # echo "Dsymifying and stripping executables:"
545 # if [ -z "${bundle_binary_list[@]}" ] ; then
546 # echo "No executables specified for dsymifying."
547 # exit 1
548 # fi
549 # for binary in "${bundle_binary_list[@]}" ; do
550 # if [ -e "$binary" ];then
551 # dsymify_file "$binary"
552 # fi
553 # done
555 # echo "Dsymifying and stripping frameworks:"
556 # for framework in "$pkglib"/*.framework/Versions/*/* ; do
557 # if [ -f "$framework" ];then
558 # dsymify_file "$framework"
559 # fi
560 # done
562 # echo "Dsymifying and stripping libraries:"
563 # for library in "$pkglib"/*.dylib ; do
565 # # Squelch warnings, in case the .o files from building
566 # # support libraries aren't around any more.
568 # dsymify_file "$library" | grep -E -v 'unable to open object file'
569 # done
571 # echo "Dsymifying and stripping plugins:"
572 # for plugin in "$pkgplugin"/*/*.so ; do
573 # dsymify_file "$plugin"
574 # done
576 codesign_file () {
577 # https://developer.apple.com/forums/thread/128166
578 # https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html
579 # https://developer.apple.com/library/archive/technotes/tn2206/_index.html
580 # https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/resolving_common_notarization_issues?language=objc
582 # XXX Do we need to add the com.apple.security.cs.allow-unsigned-executable-memory
583 # entitlement for Lua?
584 # https://developer.apple.com/documentation/security/hardened_runtime_entitlements?language=objc
586 codesign \
587 --sign "$codesign_dev_app_identity" \
588 --prefix "org.wireshark." \
589 --force \
590 --options runtime \
591 --entitlements "@CMAKE_SOURCE_DIR@/packaging/macosx/entitlements.plist" \
592 --timestamp \
593 --verbose \
594 "$1" || exit 1
597 # XXX We could do this via the productbuild calls in the {,un}install_*_pkg
598 # targets in CMakeLists.txt instead.
599 productsign_pkg () {
600 mv "$1" "$1.unsigned" || exit 1
601 productsign \
602 --sign "$codesign_dev_install_identity" \
603 --timestamp \
604 "$1.unsigned" "$1" || exit 1
605 rm -f "$1.unsigned" || exit 1
608 if [ -n "$CODE_SIGN_IDENTITY" ] ; then
609 security find-identity -v -s "$CODE_SIGN_IDENTITY" -p codesigning
611 # The Code Signing Guide says:
613 # "While you use the --deep option for verification to mimic what Gatekeeper does,
614 # it is not recommended for signing. During signing, if you have nested code, and
615 # if you are signing manually, you sign nested code in stages (as Xcode does
616 # automatically), starting with the most deeply embedded components first. You
617 # then sign code at the next level of hierarchy, and so on. You work your way
618 # outward, finally signing the top level entity that contains all the others.
619 # Signing all the components in one shot with --deep is for emergency repairs and
620 # temporary adjustments only. Note that signing with the combination --deep
621 # --force will forcibly re-sign all code in a bundle."
623 # We need to force-sign Sparkle and its Updater.app.
624 # https://sparkle-project.org/documentation/#4-distributing-your-app
625 # https://sparkle-project.org/documentation/sandboxing/#code-signing
627 if [ "$sparkle_version" == "2" ] ; then
628 echo "Signing Sparkle's assets"
629 codesign \
630 --sign "$codesign_dev_app_identity" \
631 --force \
632 --options runtime \
633 --verbose \
634 "$pkglib/Sparkle.framework/Versions/B/AutoUpdate" \
635 "$pkglib/Sparkle.framework/Versions/B/Updater.app" \
636 "$pkglib/Sparkle.framework" \
637 || exit 1
638 # Uncomment if we ever start sandboxing.
639 # "$pkglib/Sparkle.framework/Versions/B/XPCServices/org.sparkle-project.InstallerLauncher.xpc"
640 # codesign \
641 # --sign "$codesign_dev_app_identity" \
642 # --force \
643 # --options runtime \
644 # --entitlements "$sparkle_frameworks_dir/../Entitlements/org.sparkle-project.Downloader.entitlements" \
645 # --verbose \
646 # "$pkglib/Sparkle.framework/Versions/B/XPCServices/org.sparkle-project.Downloader.xpc" \
647 # || exit 1
648 else
649 echo "Signing Sparkle's AutoUpdate.app"
650 codesign \
651 --sign "$codesign_dev_app_identity" \
652 --force \
653 --timestamp \
654 --options runtime \
655 --verbose \
656 "$pkglib/Sparkle.framework/Versions/A/Resources/AutoUpdate.app" \
657 || exit 1
660 echo "Signing frameworks"
661 for framework in "$pkglib"/*.framework/Versions/* ; do
662 if [ -L "$framework" ] ; then
663 # Skip "Current"
664 continue
666 codesign_file "$framework"
667 done
669 echo "Signing libraries"
670 for library in "$pkglib"/*.dylib ; do
671 codesign_file "$library"
672 done
674 plugin_list=$( find "$bundle/Contents/PlugIns" -type f -name "*.dylib" -o -name "*.so" )
675 echo "Signing plugins"
676 for plugin in $plugin_list ; do
677 codesign_file "$plugin"
678 done
680 echo "Signing extra packages"
681 find "$bundle/Contents/Resources/Extras" -type f -name "*.pkg" | \
682 while read -r extra_pkg ; do
683 productsign_pkg "$extra_pkg"
684 done
686 echo "Signing secondary executables"
687 if (( ! ${#secondary_binary_list[@]} )) ; then
688 echo "No executables specified for code signing."
689 exit 1
691 for binary in "${secondary_binary_list[@]}" ; do
692 if [ -e "$binary" ];then
693 codesign_file "$binary"
695 done
697 echo "Signing primary executable"
698 codesign_file "$pkgexec/$app_name"
700 echo "Signing $bundle"
701 codesign_file "$bundle"
703 # Code Signing Guide, "Testing Conformance with Command Line Tools"
704 codesign --verify --deep --strict --verbose=2 "$bundle" || exit 1
705 spctl --assess --type exec --verbose=2 "$bundle" || exit 1
706 else
707 echo "Code signing not performed (no identity)"
710 # File permission sanity check.
711 if badperms=$( find "$bundle" ! -perm -0444 -exec ls -l "{}" + | grep . ) ; then
712 echo "Found files with restrictive permissions:"
713 echo "$badperms"
714 exit 1
717 exit 0