Index: pkg/mac/codesign-binaries.sh =================================================================== --- pkg/mac/codesign-binaries.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/codesign-binaries.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) @@ -1,36 +0,0 @@ -#!/bin/sh -BUNDLE="$1" - -if ! test -d "${BUNDLE}" ; then - echo "${BUNDLE} is no bundle!" >&2 - exit 1 -fi - -# Get the config -source codesign.conf - -if [ -z "${DEVELOPER_ID}" ] ; then - echo "Developer ID Application not found in codesign.conf" >&2 - exit 1 -fi - -if [ -z "${DEVELOPER_BUNDLE_ID}" ]; then - echo "Developer Bundle Identifier not found in codesign.conf" >&2 -fi - -echo Signing ${BUNDLE} binaries -IFS=$'\n' -for i in $(find "${BUNDLE}" -type f) -do - file "${i}" | grep -E "Mach-O executable|Mach-O 64-bit executable|Mach-O 64-bit bundle" - if [ $? -eq 0 ] ; then - codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "$i" - fi -done - -echo Signing ${BUNDLE} libraries -for i in $(find "${BUNDLE}" -type f -name "*.dylib*") -do - codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "$i" -done - Index: pkg/mac/codesign-bundle.sh =================================================================== --- pkg/mac/codesign-bundle.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/codesign-bundle.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) @@ -1,26 +0,0 @@ -#!/bin/sh - -BUNDLE="$1" - -if ! test -d "${BUNDLE}" ; then - echo "${BUNDLE} is no bundle!" >&2 - exit 1 -fi - -# Get the config -source codesign.conf - -# Sign the .app -echo Signing ${BUNDLE} -codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "${BUNDLE}" - -# Verify it worked -echo Verifying the signature -codesign --verify --verbose --deep --force "${BUNDLE}" -RETURN_STATUS=$? -if [ ${RETURN_STATUS} -ne 0 ]; then - echo Code signing did not work, check the log - exit 1 -else - echo ${BUNDLE} successfully signed -fi Index: pkg/mac/codesign-dmg.sh =================================================================== --- pkg/mac/codesign-dmg.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/codesign-dmg.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) @@ -1,30 +0,0 @@ -#!/bin/bash - -DMG_VOLUME_NAME=${APP_NAME} -DMG_NAME=`echo ${DMG_VOLUME_NAME} | sed 's/ //g' | awk '{print tolower($0)}'` -DMG_IMAGE=${DISTROOT}/${DMG_NAME}-${APP_LONG_VERSION}.dmg - -if ! test -f "${DMG_IMAGE}" ; then - echo "${DMG_IMAGE} is no disk image!" >&2 - exit 1 -fi - -# Get the config -source codesign.conf - -SCRIPT_DIR=`pwd` - -# Sign the .app -echo Signing ${DMG_IMAGE} -codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "${DMG_IMAGE}" - -# Verify it worked -echo Verifying the signature -codesign --verify --verbose --force "${DMG_IMAGE}" -RETURN_STATUS=$? -if [ ${RETURN_STATUS} -ne 0 ]; then - echo ERROR: Code signing did not work - exit 1 -else - echo ${DMG_IMAGE} successfully signed -fi Index: pkg/mac/create-dmg.sh =================================================================== --- pkg/mac/create-dmg.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/create-dmg.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) @@ -1,36 +0,0 @@ -#!/bin/sh - -# move to the directory where we want to create the DMG -test -d ${DISTROOT} || mkdir ${DISTROOT} -cd ${DISTROOT} - -DMG_SOURCES="./../mac-build/${APP_BUNDLE_NAME}" -DMG_LICENCE=./../pkg/mac/licence.rtf -DMG_VOLUME_NAME=${APP_NAME} -DMG_NAME=`echo ${DMG_VOLUME_NAME} | sed 's/ //g' | awk '{print tolower($0)}'` -DMG_IMAGE=${DMG_NAME}-${APP_LONG_VERSION}.dmg -HDIUTIL=/usr/bin/hdiutil -REZ="/usr/bin/Rez" - -DMG_DIR=./${DMG_IMAGE}.src - -if test -e "${DMG_DIR}"; then - echo "Directory ${DMG_DIR} already exists. Please delete it manually." >&2 - exit 1 -fi - -echo "Cleaning up" -rm -f "${DMG_IMAGE}" || exit 1 -mkdir "${DMG_DIR}" || exit 1 - -echo "Copying data into temporary directory" -for src in "${DMG_SOURCES}"; do - cp -R "${src}" "${DMG_DIR}" || exit 1 -done - -echo "Creating image" -${HDIUTIL} create -quiet -srcfolder "$DMG_DIR" -fs HFS+ -format UDZO -volname "${DMG_VOLUME_NAME}" -ov "${DMG_IMAGE}" || exit 1 -rm -rf "${DMG_DIR}" || exit 1 - -echo "Attaching License to image" -python ./../pkg/mac/dmg-license.py "${DMG_IMAGE}" "${DMG_LICENCE}" -c bz2 Index: pkg/mac/framework-config.sh =================================================================== --- pkg/mac/framework-config.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/framework-config.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) @@ -1,71 +0,0 @@ -#!/bin/sh - -BUNDLE="$1" - -if ! test -d "${BUNDLE}" ; then - echo "${BUNDLE} is no bundle!" >&2 - exit 1 -fi - -# Get the config -source framework.conf - -SCRIPT_DIR=`pwd` - -echo Reorganising the framework structure - -# Create "Current" and "Current/Resources" inside each of the framework dirs -MYDIR=`pwd` -find "${BUNDLE}/Contents/Frameworks"/*framework -type d -name "Versions" | while read -r framework_dir; do - cd "${framework_dir}" - - # Create framework 'Current' soft link - VERSION_NUMBER=`ls -1` - ln -s ${VERSION_NUMBER} Current || { echo "link creation in framework-config.sh failed"; exit 1; } - - # Create "Resources" subdirectory - if [ ! -d Current/Resources ]; then - mkdir Current/Resources - fi - - cd "${MYDIR}" -done - -# Stuff for Qt framework files only -find "${BUNDLE}/Contents/Frameworks" -type d -name "Qt*framework" | while read -r framework_dir; do - cd "${framework_dir}" - - # Create soft link to the framework binary - ln -s Versions/Current/Qt* || { echo "link creation in framework-config.sh failed"; exit 1; } - - # Create soft link to the framework Resources dir - ln -s Versions/Current/Resources || { echo "link creation in framework-config.sh failed"; exit 1; } - - # Create the Info.plist files - MYNAME=`ls -1 Qt*` - if [ -f Resources/Info.plist ]; then - chmod +w Resources/Info.plist - fi - sed 's/__SHORT_VERSION__/${QT_SHORT_VERSION}/' "${SCRIPT_DIR}/Info.plist-template_Qt5" | sed 's/__FULL_VERSION__/${QT_FULL_VERSION}/' | sed "s/__FRAMEWORK_NAME__/${MYNAME}/" > "Resources/Info.plist" || { echo "sed replacement in framework-config.sh failed"; exit 1; } - - cd "${MYDIR}" -done - -# Same thing, but specific to the Python framework dir -find "${BUNDLE}/Contents/Frameworks" -type d -name "P*framework" | while read -r framework_dir; do - cd "${framework_dir}" - - # Create soft link to the framework binary - ln -s Versions/Current/Py* || { echo "link creation in framework-config.sh failed"; exit 1; } - - # Create soft link to the framework Resources dir - ln -s Versions/Current/Resources || { echo "link creation in framework-config.sh failed"; exit 1; } - - # Create the Info.plist file - MYNAME=`ls -1 Py*` - sed 's/__SHORT_VERSION__/${PYTHON_SHORT_VERSION}/' "${SCRIPT_DIR}/Info.plist-template_Python" | sed 's/__FULL_VERSION__/${PYTHON_FULL_VERSION}/' | sed "s/__FRAMEWORK_NAME__/${MYNAME}/" > "Resources/Info.plist" || { echo "sed replacement in framework-config.sh failed"; exit 1; } - - cd "${MYDIR}" -done - -echo ${BUNDLE} framework config finished Index: pkg/mac/build-functions.sh IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- pkg/mac/build-functions.sh (date 1589445174016) +++ pkg/mac/build-functions.sh (date 1589445174016) @@ -0,0 +1,387 @@ +_setup_env() { + APP_RELEASE=`grep "^APP_RELEASE" web/config.py | cut -d"=" -f2 | sed 's/ //g'` + APP_REVISION=`grep "^APP_REVISION" web/config.py | cut -d"=" -f2 | sed 's/ //g'` + APP_NAME=`grep "^APP_NAME" web/config.py | cut -d"=" -f2 | sed "s/'//g" | sed 's/^ //'` + APP_LONG_VERSION=${APP_RELEASE}.${APP_REVISION} + APP_SHORT_VERSION=`echo ${APP_LONG_VERSION} | cut -d . -f1,2` + APP_SUFFIX=`grep "^APP_SUFFIX" web/config.py | cut -d"=" -f2 | sed 's/ //g' | sed "s/'//g"` + if [ ! -z ${APP_SUFFIX} ]; then + APP_LONG_VERSION=${APP_LONG_VERSION}-${APP_SUFFIX} + fi + BUNDLE_DIR="${BUILD_ROOT}/${APP_NAME}.app" +} + +_cleanup() { + echo Cleaning up the old environment and app bundle... + rm -rf ${SOURCE_DIR}/runtime/*.app + rm -rf ${BUILD_ROOT} + rm -f ${DIST_ROOT}/*.dmg +} + +_create_venv() { + PATH=${PGDIR}/bin:${PATH} + LD_LIBRARY_PATH=${PGDIR}/lib:${LD_LIBRARY_PATH} + + test -d ${BUILD_ROOT} || mkdir ${BUILD_ROOT} + cd ${BUILD_ROOT} + + ${PYTHON_EXE} -m venv --copies venv + + source venv/bin/activate + pip install --no-cache-dir --no-binary psycopg2 -r ${SOURCE_DIR}/requirements.txt + + # Figure the source path for use when completing the venv + SOURCE_PYMODULES_PATH=$(dirname $("${PYTHON_EXE}" -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")) + + # Figure the target path for use when completing the venv + # Use "python" here as we want the venv path + TARGET_PYMODULES_PATH=$(dirname $(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")) + + # Copy in the additional system python modules + cp -R ${SOURCE_PYMODULES_PATH}/* "${TARGET_PYMODULES_PATH}/" + + # Link the python directory to python so that the private environment path is found by the application. + ln -s "$(basename ${TARGET_PYMODULES_PATH})" "${TARGET_PYMODULES_PATH}/../python" + + # Remove tests + find venv -name "test" -type d -print0 | xargs -0 rm -rf + find venv -name "tests" -type d -print0 | xargs -0 rm -rf +} + +_build_runtime() { + cd ${SOURCE_DIR}/runtime + make clean + ${QMAKE} + make + cp -r pgAdmin4.app "${BUNDLE_DIR}" +} + +_build_docs() { + cd ${SOURCE_DIR}/docs/en_US + test -d "${BUNDLE_DIR}/Contents/Resources/docs/en_US" || mkdir -p "${BUNDLE_DIR}/Contents/Resources/docs/en_US" + cp -r _build/html "${BUNDLE_DIR}/Contents/Resources/docs/en_US/" +} + +_complete_bundle() { + cd ${SCRIPT_DIR} + + # Copy the binary utilities into place + mkdir -p "${BUNDLE_DIR}/Contents/SharedSupport/" + cp "${PGDIR}/bin/pg_dump" "${BUNDLE_DIR}/Contents/SharedSupport/" + cp "${PGDIR}/bin/pg_dumpall" "${BUNDLE_DIR}/Contents/SharedSupport/" + cp "${PGDIR}/bin/pg_restore" "${BUNDLE_DIR}/Contents/SharedSupport/" + cp "${PGDIR}/bin/psql" "${BUNDLE_DIR}/Contents/SharedSupport/" + + # Replace the place holders with the current version + sed -e "s/PGADMIN_LONG_VERSION/${APP_LONG_VERSION}/g" -e "s/PGADMIN_SHORT_VERSION/${APP_SHORT_VERSION}/g" pgadmin.Info.plist.in > pgadmin.Info.plist + + # copy Python private environment to app bundle + cp -PR ${BUILD_ROOT}/venv "${BUNDLE_DIR}/Contents/Resources/" + + # Remove any TCL-related files that may cause us problems + find "${BUNDLE_DIR}/Contents/Resources/venv/" -name "_tkinter*" -print0 | xargs -0 rm -f + + test -d "${BUNDLE_DIR}/Contents/Resources" || mkdir -p "${BUNDLE_DIR}/Contents/Resources" + # Create qt.conf so that app knows where the Plugins are present + cat >> "${BUNDLE_DIR}/Contents/Resources/qt.conf" << EOF +[Paths] +Plugins = PlugIns +EOF + + test -d "${BUNDLE_DIR}/Contents/Frameworks" || mkdir -p "${BUNDLE_DIR}/Contents/Frameworks" + test -d "${BUNDLE_DIR}/Contents/PlugIns/platforms" || mkdir -p "${BUNDLE_DIR}/Contents/PlugIns/platforms" + test -d "${BUNDLE_DIR}/Contents/PlugIns/imageformats" || mkdir -p "${BUNDLE_DIR}/Contents/PlugIns/imageformats" + cp -f ${QTDIR}/plugins/platforms/libqcocoa.dylib "${BUNDLE_DIR}/Contents/PlugIns/platforms" + cp -f ${QTDIR}/plugins/imageformats/libqsvg.dylib "${BUNDLE_DIR}/Contents/PlugIns/imageformats" + cp -f ${PGDIR}/lib/libpq.5.dylib "${BUNDLE_DIR}/Contents/Frameworks" + + local bundle=$1 todo todo_old fw_relpath lib lib_bn nested_app na_relpath + + pushd "${BUNDLE_DIR}" > /dev/null + + # We skip nested apps here - those are treated specially + todo=$(file `find ./ -perm +0111 ! -type d ! -path "*.app/*" ! -name "*.app"` | grep -E "Mach-O 64-bit" | awk -F ':| ' '{ORS=" "; print $1}') + + echo "Found executables: ${todo}" + while test "${todo}" != ""; do + todo_old=${todo} ; + todo="" ; + for todo_obj in ${todo_old}; do + echo "Post-processing: ${todo_obj}" + + # Figure out the relative path from todo_obj to Contents/Frameworks + fw_relpath=$(echo "${todo_obj}" | sed -n 's|^\(\.//*\)\(\([^/][^/]*/\)*\)[^/][^/]*$|\2|gp' | sed -n 's|[^/][^/]*/|../|gp')"Contents/Frameworks" + fw_relpath_old=${fw_relpath} + + fw_loc="Contents/Frameworks" + + # Find all libraries $todo_obj depends on, but skip system libraries + for lib in $(otool -L ${todo_obj} | grep "Qt\|dylib\|Frameworks\|PlugIns" | grep -v ":" | sed 's/(.*//' | egrep -v '(/usr/lib)|(/System)|@executable_path@'); do + if echo ${lib} | grep "PlugIns\|libqcocoa" > /dev/null; then + lib_loc="Contents/PlugIns/platforms" + elif echo ${lib} | grep "PlugIns\|libqsvg" > /dev/null; then + lib_loc="Contents/PlugIns/imageformats" + elif echo ${lib} | grep "Qt" > /dev/null; then + qtfw_path="$(dirname ${lib} | sed 's|.*\(Qt.*framework\)|\1|')" + lib_loc="Contents/Frameworks/${qtfw_path}" + if [ "$(basename ${todo_obj})" = "${lib}" ]; then + lib_loc="$(dirname ${todo_obj})" + qtfw_path=$(echo ${lib_loc} | sed 's/Contents\/Frameworks\///') + fi + elif echo ${lib} | grep "Python" > /dev/null; then + pyfw_path="$(dirname ${lib} | sed 's|.*\(Python.*framework\)|\1|')" + lib_loc="Contents/Frameworks/${pyfw_path}" + if [ "$(basename ${todo_obj})" = "${lib}" ]; then + lib_loc="$(dirname ${todo_obj})" + pyfw_path=$(echo ${lib_loc} | sed 's/Contents\/Frameworks\///') + fi + else + lib_loc="Contents/Frameworks" + fi + lib_bn="$(basename "${lib}")" ; + if ! test -f "${lib_loc}/${lib_bn}"; then + target_file="" + target_path="" + echo "Adding symlink: ${lib_bn} (because of: ${todo_obj})" + + # Copy the QT and Python framework + if echo ${lib} | grep Qt > /dev/null ; then + test -d ${lib_loc} || mkdir -p ${lib_loc} + echo Copying -R ${QTDIR}/lib/${qtfw_path}/${lib_bn} to ${lib_loc}/ + cp ${QTDIR}/lib/${qtfw_path}/${lib_bn} ${lib_loc}/ + elif echo ${lib} | grep Python > /dev/null ; then + test -d ${lib_loc} || mkdir -p ${lib_loc} + cp -R "${lib}" "${lib_loc}/${lib_bn}" + else + cp -R "${lib}" "${lib_loc}/${lib_bn}" + fi + if ! test -L "${lib_loc}/${lib_bn}"; then + chmod 755 "${lib_loc}/${lib_bn}" + else + target_file=$(readlink "${lib}") + target_path=$(dirname "${lib}")/${target_file} + + echo "Adding symlink target: ${target_path}" + cp "${target_path}" "${lib_loc}/${target_file}" + chmod 755 "${lib_loc}/${target_file}" + fi + echo "Rewriting ID in ${lib_loc}/${lib_bn} to ${lib_bn}" + install_name_tool -id "${lib_bn}" "${lib_loc}/${lib_bn}" + + todo="${todo} ./${lib_loc}/${lib_bn}" + fi + if echo ${lib} | grep Qt > /dev/null ; then + fw_relpath="${fw_relpath}/${qtfw_path}" + fi + if echo ${lib} | grep Python > /dev/null ; then + fw_relpath="${fw_relpath}/${pyfw_path}" + fi + chmod +w ${todo_obj} + echo "Rewriting library ${lib} to @loader_path/${fw_relpath}/${lib_bn} in ${todo_obj}" + + install_name_tool -change "${lib}" "@loader_path/${fw_relpath}/${lib_bn}" "${todo_obj}" + install_name_tool -change "${target_path}" "@loader_path/${fw_relpath}/${target_file}" "${todo_obj}" + + fw_relpath="${fw_relpath_old}" + done + done + done + + # Fix the rpaths for psycopg module + find "${BUNDLE_DIR}/Contents/Resources/venv/" -name _psycopg.so -print0 | xargs -0 install_name_tool -change libpq.5.dylib @loader_path/../../../../../../Frameworks/libpq.5.dylib + find "${BUNDLE_DIR}/Contents/Resources/venv/" -name _psycopg.so -print0 | xargs -0 install_name_tool -change libssl.1.0.0.dylib @loader_path/../../../../../../Frameworks/libssl.1.0.0.dylib + find "${BUNDLE_DIR}/Contents/Resources/venv/" -name _psycopg.so -print0 | xargs -0 install_name_tool -change libcrypto.1.0.0.dylib @loader_path/../../../../../../Frameworks/libcrypto.1.0.0.dylib + + echo "App completed: ${BUNDLE_DIR}" + popd > /dev/null + + pushd ${SOURCE_DIR}/web > /dev/null + yarn install + yarn run bundle + + curl https://curl.haxx.se/ca/cacert.pem -o cacert.pem -s + popd > /dev/null + + # copy the web directory to the bundle as it is required by runtime + cp -r ${SOURCE_DIR}/web "${BUNDLE_DIR}/Contents/Resources/" + cd "${BUNDLE_DIR}/Contents/Resources/web" + rm -f pgadmin4.db config_local.* + rm -rf karma.conf.js package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache + find . -name "tests" -type d -print0 | xargs -0 rm -rf + find . -name "feature_tests" -type d -print0 | xargs -0 rm -rf + find . -name ".DS_Store" -print0 | xargs -0 rm -f + + echo "SERVER_MODE = False" > config_distro.py + echo "HELP_PATH = '../../../docs/en_US/html/'" >> config_distro.py + echo "DEFAULT_BINARY_PATHS = {" >> config_distro.py + echo " 'pg': '\$DIR/../../SharedSupport'," >> config_distro.py + echo " 'ppas': ''" >> config_distro.py + echo "}" >> config_distro.py + + # Remove the .pyc files if any + find "${BUNDLE_DIR}" -name *.pyc -print0 | xargs -0 rm -f +} + +_framework_config() { + # Get the config + source ${SCRIPT_DIR}/framework.conf + + echo Reorganising the framework structure... + + # Create "Current" and "Current/Resources" inside each of the framework dirs + find "${BUNDLE_DIR}/Contents/Frameworks"/*framework -type d -name "Versions" | while read -r framework_dir; do + pushd "${framework_dir}" > /dev/null + + # Create framework 'Current' soft link + VERSION_NUMBER=`ls -1` + ln -s ${VERSION_NUMBER} Current + + # Create "Resources" subdirectory + if [ ! -d Current/Resources ]; then + mkdir Current/Resources + fi + + popd > /dev/null + done + + # Stuff for Qt framework files only + find "${BUNDLE_DIR}/Contents/Frameworks" -type d -name "Qt*framework" | while read -r framework_dir; do + pushd "${framework_dir}" > /dev/null + + # Create soft link to the framework binary + ln -s Versions/Current/Qt* + + # Create soft link to the framework Resources dir + ln -s Versions/Current/Resources + + # Create the Info.plist files + MYNAME=`ls -1 Qt*` + if [ -f Resources/Info.plist ]; then + chmod +w Resources/Info.plist + fi + sed 's/__SHORT_VERSION__/${QT_SHORT_VERSION}/' "${SCRIPT_DIR}/Info.plist-template_Qt5" | sed 's/__FULL_VERSION__/${QT_FULL_VERSION}/' | sed "s/__FRAMEWORK_NAME__/${MYNAME}/" > "Resources/Info.plist" + + popd > /dev/null + done + + # Same thing, but specific to the Python framework dir + find "${BUNDLE_DIR}/Contents/Frameworks" -type d -name "P*framework" | while read -r framework_dir; do + pushd "${framework_dir}" > /dev/null + + # Create soft link to the framework binary + ln -s Versions/Current/Py* + + # Create soft link to the framework Resources dir + ln -s Versions/Current/Resources + + # Create the Info.plist file + MYNAME=`ls -1 Py*` + sed 's/__SHORT_VERSION__/${PYTHON_SHORT_VERSION}/' "${SCRIPT_DIR}/Info.plist-template_Python" | sed 's/__FULL_VERSION__/${PYTHON_FULL_VERSION}/' | sed "s/__FRAMEWORK_NAME__/${MYNAME}/" > "Resources/Info.plist" + + popd > /dev/null + done +} + +_codesign_binaries() { + if [ ${CODESIGN} -eq 0 ]; then + return + fi + + if [ -z "${DEVELOPER_ID}" ] ; then + echo "Developer ID Application not found in codesign.conf" >&2 + exit 1 + fi + + if [ -z "${DEVELOPER_BUNDLE_ID}" ]; then + echo "Developer Bundle Identifier not found in codesign.conf" >&2 + fi + + echo Signing ${BUNDLE_DIR} binaries... + IFS=$'\n' + for i in $(find "${BUNDLE_DIR}" -type f -perm +111 -exec file "{}" \; | grep -E "Mach-O executable|Mach-O 64-bit executable|Mach-O 64-bit bundle" | awk -F":| \\\(" '{print $1}' | uniq) + do + codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "$i" + done + + echo Signing ${BUNDLE_DIR} libraries... + for i in $(find "${BUNDLE_DIR}" -type f -name "*.dylib*") + do + codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "$i" + done +} + +_codesign_bundle() { + if [ ${CODESIGN} -eq 0 ]; then + return + fi + + # Sign the .app + echo Signing ${BUNDLE_DIR}... + codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "${BUNDLE_DIR}" + + # Verify it worked + echo Verifying the signature... + codesign --verify --verbose --deep --force "${BUNDLE_DIR}" + echo ${BUNDLE_DIR} successfully signed. +} + +_create_dmg() { + # move to the directory where we want to create the DMG + test -d ${DIST_ROOT} || mkdir ${DIST_ROOT} + cd ${DIST_ROOT} + + DMG_SOURCES="./../mac-build/${APP_NAME}.app" + DMG_LICENCE=./../pkg/mac/licence.rtf + DMG_VOLUME_NAME=${APP_NAME} + DMG_NAME=`echo ${DMG_VOLUME_NAME} | sed 's/ //g' | awk '{print tolower($0)}'` + DMG_IMAGE=${DMG_NAME}-${APP_LONG_VERSION}.dmg + HDIUTIL=/usr/bin/hdiutil + REZ="/usr/bin/Rez" + + DMG_DIR=./${DMG_IMAGE}.src + + if test -e "${DMG_DIR}"; then + echo "Directory ${DMG_DIR} already exists. Please delete it manually." >&2 + exit 1 + fi + + echo "Cleaning up" + rm -f "${DMG_IMAGE}" + mkdir "${DMG_DIR}" + + echo "Copying data into temporary directory" + for src in "${DMG_SOURCES}"; do + cp -R "${src}" "${DMG_DIR}" + done + + echo "Creating image" + ${HDIUTIL} create -quiet -srcfolder "$DMG_DIR" -fs HFS+ -format UDZO -volname "${DMG_VOLUME_NAME}" -ov "${DMG_IMAGE}" + rm -rf "${DMG_DIR}" + + echo Attaching License to image... + python ${SCRIPT_DIR}/dmg-license.py "${DMG_IMAGE}" "${DMG_LICENCE}" -c bz2 +} + +_codesign_dmg() { + if [ ${CODESIGN} -eq 0 ]; then + return + fi + + DMG_VOLUME_NAME=${APP_NAME} + DMG_NAME=`echo ${DMG_VOLUME_NAME} | sed 's/ //g' | awk '{print tolower($0)}'` + DMG_IMAGE=${DIST_ROOT}/${DMG_NAME}-${APP_LONG_VERSION}.dmg + + if ! test -f "${DMG_IMAGE}" ; then + echo "${DMG_IMAGE} is no disk image!" >&2 + exit 1 + fi + + # Sign the .app + echo Signing ${DMG_IMAGE}... + codesign --deep --force --verify --verbose --timestamp --options runtime -i "${DEVELOPER_BUNDLE_ID}" --sign "${DEVELOPER_ID}" "${DMG_IMAGE}" + + # Verify it worked + echo Verifying the signature... + codesign --verify --verbose --force "${DMG_IMAGE}" + echo ${DMG_IMAGE} successfully signed. +} \ No newline at end of file Index: docs/en_US/release_notes_4_22.rst IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- docs/en_US/release_notes_4_22.rst (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ docs/en_US/release_notes_4_22.rst (date 1589462888768) @@ -18,6 +18,7 @@ | `Issue #5443 `_ - Remove support for Python 2. | `Issue #5444 `_ - Cleanup Python detection in the runtime project file. | `Issue #5455 `_ - Refactor pgAdmin4.py so it can be imported and is a lot more readable. +| `Issue #5525 `_ - Cleanup and refactor the macOS build scripts. Bug fixes ********* Index: pkg/mac/build.sh IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- pkg/mac/build.sh (revision 12a7ce54d93346e49efe1b14d1ad61d949adbbcc) +++ pkg/mac/build.sh (date 1589206120250) @@ -2,13 +2,19 @@ # Build script to create Mac App Bundle and DMG for pgAdmin4 runtime -export WD=$(cd `dirname $0` && pwd) -export SOURCEDIR=${WD}/../.. -export BUILDROOT=${WD}/../../mac-build -export DISTROOT=${WD}/../../dist -export VIRTUALENV=venv +# Exit when any command fails +set -e -E + +# Debugging shizz +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT -if [ ! -f ${SOURCEDIR}/pkg/mac/framework.conf ]; then +SCRIPT_DIR=$(cd `dirname $0` && pwd) +SOURCE_DIR=$(realpath ${SCRIPT_DIR}/../..) +BUILD_ROOT=$(realpath ${SCRIPT_DIR}/../..)/mac-build +DIST_ROOT=$(realpath ${SCRIPT_DIR}/../..)/dist + +if [ ! -f ${SCRIPT_DIR}/framework.conf ]; then echo echo "Error: pkg/mac/framework.conf not found!" echo "Copy pkg/mac/framework.conf.in to pkg/mac/framework.conf and edit as required for the current system." @@ -16,14 +22,28 @@ exit 1 fi -if [ "x${PYTHON_HOME}" == "x" ]; then - echo "PYTHON_HOME not set. It must be set, and pointing to a Python 3 installation." +CODESIGN=1 +if [ ! -f ${SCRIPT_DIR}/codesign.conf ]; then + echo + echo "******************************************************************" + echo "* ${SCRIPT_DIR}/codesign.conf not found. NOT signing the binaries." + echo "******************************************************************" + echo + CODESIGN=0 + sleep 5 +else + source ${SCRIPT_DIR}/codesign.conf +fi + +if [ "x${PGADMIN_PYTHON_DIR}" == "x" ]; then + echo "PGADMIN_PYTHON_DIR not set. It must be set, and pointing to a Python 3 installation." exit 1 fi +PYTHON_EXE=${PGADMIN_PYTHON_DIR}/bin/python3 # Check if Python is working and calculate PYTHON_VERSION -if ${PYTHON_HOME}/bin/python3 -V > /dev/null 2>&1; then - export PYTHON_VERSION=`${PYTHON_HOME}/bin/python3 -V 2>&1 | awk '{print $2}' | cut -d"." -f1-2 | sed 's/\.//'` +if ${PYTHON_EXE} -V > /dev/null 2>&1; then + PYTHON_VERSION=`${PYTHON_EXE} -V 2>&1 | awk '{print $2}' | cut -d"." -f1-2 | sed 's/\.//'` else echo "Error: Python installation missing!" exit 1 @@ -34,14 +54,12 @@ exit 1 fi -export PYTHON=${PYTHON_HOME}/bin/python3 -export PIP=pip3 - if [ "x${QTDIR}" == "x" ]; then echo "QTDIR not set. Setting it to default." - export QTDIR=~/Qt/5.8/clang_64 + export QTDIR=~/Qt/5.13.2/clang_64 fi -export QMAKE=${QTDIR}/bin/qmake + +QMAKE=${QTDIR}/bin/qmake if ! ${QMAKE} --version > /dev/null 2>&1; then echo "Error: qmake not found. QT installation is not present or incomplete." exit 1 @@ -52,208 +70,13 @@ export PGDIR=/usr/local/pgsql fi -_get_version() { - export APP_RELEASE=`grep "^APP_RELEASE" web/config.py | cut -d"=" -f2 | sed 's/ //g'` - export APP_REVISION=`grep "^APP_REVISION" web/config.py | cut -d"=" -f2 | sed 's/ //g'` - export APP_NAME=`grep "^APP_NAME" web/config.py | cut -d"=" -f2 | sed "s/'//g" | sed 's/^ //'` - export APP_BUNDLE_NAME=${APP_NAME}.app - export APP_LONG_VERSION=${APP_RELEASE}.${APP_REVISION} - export APP_SHORT_VERSION=`echo ${APP_LONG_VERSION} | cut -d . -f1,2` - export APP_SUFFIX=`grep "^APP_SUFFIX" web/config.py | cut -d"=" -f2 | sed 's/ //g' | sed "s/'//g"` - if [ ! -z ${APP_SUFFIX} ]; then - export APP_LONG_VERSION=${APP_LONG_VERSION}-${APP_SUFFIX} - fi -} - -_cleanup() { - echo "Cleaning up the old environment and app bundle" - rm -rf ${SOURCEDIR}/runtime/pgAdmin4.app - rm -rf ${BUILDROOT} - rm -f ${DISTROOT}/pgadmin4*.dmg -} - -_create_venv() { - export PATH=${PGDIR}/bin:${PATH} - export LD_LIBRARY_PATH=${PGDIR}/lib:${LD_LIBRARY_PATH} - test -d ${BUILDROOT} || mkdir ${BUILDROOT} || exit 1 - cd ${BUILDROOT} - - test -d ${VIRTUALENV} || virtualenv -p ${PYTHON} --always-copy ${VIRTUALENV} || exit 1 - - source ${VIRTUALENV}/bin/activate - ${PIP} install --no-cache-dir --no-binary psycopg2 -r ${SOURCEDIR}/requirements.txt || { echo PIP install failed. Please resolve the issue and rerun the script; exit 1; } - - # Figure out some paths for use when completing the venv - # Use "python" here as we want the venv path - export PYMODULES_PATH=`python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"` - export DIR_PYMODULES_PATH=`dirname ${PYMODULES_PATH}` - - # Use $PYTHON here as we want the system path - export PYSYSLIB_PATH=`${PYTHON} -c "import sys; print('%s/lib/python%d.%.d' % (sys.prefix, sys.version_info.major, sys.version_info.minor))"` - - # Symlink in the rest of the Python libs. This is required because the runtime - # will clear PYTHONHOME for safety, which has the side-effect of preventing - # it from finding modules that are not explicitly included in the venv - cd ${DIR_PYMODULES_PATH} - - # Files - for FULLPATH in ${PYSYSLIB_PATH}/*.py; do - FILE=${FULLPATH##*/} - if [ ! -e ${FILE} ]; then - cp ${FULLPATH} ${FILE} - fi - done - - # Paths - for FULLPATH in ${PYSYSLIB_PATH}/*/; do - FULLPATH=${FULLPATH%*/} - FILE=${FULLPATH##*/} - if [ ! -e ${FILE} ]; then - cp -R ${FULLPATH} ${FILE} - fi - done - - # Remove tests - cd site-packages - find . -name "test" -type d -print0 | xargs -0 rm -rf - find . -name "tests" -type d -print0 | xargs -0 rm -rf +source ${SCRIPT_DIR}/build-functions.sh - # Link the python directory to python so that the private environment path is found by the application. - if test -d ${DIR_PYMODULES_PATH}; then - ln -s $(basename ${DIR_PYMODULES_PATH}) ${DIR_PYMODULES_PATH}/../python - fi -} - -_build_runtime() { - cd ${SOURCEDIR}/runtime - make clean - PGADMIN_PYTHON_DIR=${PYTHON_HOME} ${QMAKE} || { echo qmake failed; exit 1; } - make || { echo make failed; exit 1; } - cp -r pgAdmin4.app "${BUILDROOT}/${APP_BUNDLE_NAME}" -} - -_build_doc() { - cd ${SOURCEDIR}/docs/en_US - test -d "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources" || "mkdir -p ${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources" - test -d "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/docs/en_US" || mkdir -p "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/docs/en_US" - cp -r _build/html "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/docs/en_US/" || exit 1 -} - -_complete_bundle() { - cd ${SOURCEDIR}/pkg/mac - - # Copy the binary utilities into place - mkdir -p "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/SharedSupport/" || exit 1 - cp "${PGDIR}/bin/pg_dump" "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/SharedSupport/" || exit 1 - cp "${PGDIR}/bin/pg_dumpall" "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/SharedSupport/" || exit 1 - cp "${PGDIR}/bin/pg_restore" "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/SharedSupport/" || exit 1 - cp "${PGDIR}/bin/psql" "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/SharedSupport/" || exit 1 - - # Replace the place holders with the current version - sed -e "s/PGADMIN_LONG_VERSION/${APP_LONG_VERSION}/g" -e "s/PGADMIN_SHORT_VERSION/${APP_SHORT_VERSION}/g" pgadmin.Info.plist.in > pgadmin.Info.plist - - # copy Python private environment to app bundle - cp -PR ${BUILDROOT}/${VIRTUALENV} "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/" || exit 1 - - # Remove any TCL-related files that may cause us problems - find "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/${VIRTUALENV}/" -name "_tkinter*" -print0 | xargs -0 rm -f - - # run complete-bundle to copy the dependent libraries and frameworks and fix the rpaths - ./complete-bundle.sh "${BUILDROOT}/${APP_BUNDLE_NAME}" || { echo complete-bundle.sh failed; exit 1; } - - pushd ${SOURCEDIR}/web - yarn install || exit 1 - yarn run bundle || exit 1 - - curl https://curl.haxx.se/ca/cacert.pem -o cacert.pem -s || { echo Failed to download cacert.pem; exit 1; } - popd - - # copy the web directory to the bundle as it is required by runtime - cp -r ${SOURCEDIR}/web "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/" || exit 1 - cd "${BUILDROOT}/${APP_BUNDLE_NAME}/Contents/Resources/web" - rm -f pgadmin4.db config_local.* - rm -rf karma.conf.js package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache - find . -name "tests" -type d -print0 | xargs -0 rm -rf - find . -name "feature_tests" -type d -print0 | xargs -0 rm -rf - find . -name ".DS_Store" -print0 | xargs -0 rm -f - - echo "SERVER_MODE = False" > config_distro.py - echo "HELP_PATH = '../../../docs/en_US/html/'" >> config_distro.py - echo "DEFAULT_BINARY_PATHS = {" >> config_distro.py - echo " 'pg': '\$DIR/../../SharedSupport'," >> config_distro.py - echo " 'ppas': ''" >> config_distro.py - echo "}" >> config_distro.py - - # Remove the .pyc files if any - cd "${BUILDROOT}/${APP_BUNDLE_NAME}" - find . -name *.pyc -print0 | xargs -0 rm -f -} - -_framework_config() { - cd ${SOURCEDIR}/pkg/mac - ./framework-config.sh "${BUILDROOT}/${APP_BUNDLE_NAME}" || { echo "framework-config.sh failed"; exit 1; } -} - -_codesign_binaries() { - cd ${SOURCEDIR}/pkg/mac - - if [ ! -f codesign.conf ]; then - echo - echo "******************************************************************" - echo "* codesign.conf not found. NOT signing the binaries." - echo "******************************************************************" - echo - sleep 5 - return - fi - - ./codesign-binaries.sh "${BUILDROOT}/${APP_BUNDLE_NAME}" || { echo codesign-binaries.sh failed; exit 1; } -} - -_codesign_bundle() { - cd ${SOURCEDIR}/pkg/mac - - if [ ! -f codesign.conf ]; then - echo - echo "******************************************************************" - echo "* codesign.conf not found. NOT signing the bundle." - echo "******************************************************************" - echo - sleep 5 - return - fi - - ./codesign-bundle.sh "${BUILDROOT}/${APP_BUNDLE_NAME}" || { echo codesign-bundle.sh failed; exit 1; } -} - -_create_dmg() { - cd ${SOURCEDIR} - ./pkg/mac/create-dmg.sh || { echo create-dmg.sh failed; exit 1; } - # Clean the mac-build/ on successful build - rm -rf ${BUILDROOT}/* -} - -_codesign_dmg() { - cd ${SOURCEDIR}/pkg/mac - - if [ ! -f codesign.conf ]; then - echo - echo "******************************************************************" - echo "* codesign.conf not found. NOT signing the disk image." - echo "******************************************************************" - echo - sleep 5 - return - fi - - ./codesign-dmg.sh || { echo codesign-bundle.sh failed; exit 1; } -} - -_get_version || { echo Could not get versioning; exit 1; } +_setup_env _cleanup -_create_venv || { echo venv creation failed; exit 1; } -_build_runtime || { echo Runtime build failed; exit 1; } -_build_doc +_create_venv +_build_runtime +_build_docs _complete_bundle _framework_config _codesign_binaries