Commit d76fa043efee9196899b6cb8a9964204209a6f61
Committed by
GitHub
Exists in
master
and in
4 other branches
Merge pull request #5 from andrebreves/develop
macOS .app bundle
Showing
7 changed files
with
326 additions
and
0 deletions
Show diff stats
.gitignore
README.md
| ... | ... | @@ -44,3 +44,27 @@ sudo zypper ref |
| 44 | 44 | wget https://github.com/PerryWerneck/pw3270/blob/master/win/pack.sh |
| 45 | 45 | ./pack.sh --pre-reqs |
| 46 | 46 | ``` |
| 47 | + | |
| 48 | +Building for macOS (using homebrew) | |
| 49 | +=================================== | |
| 50 | + | |
| 51 | +1. Build and install [libv3270](../../../libv3270) | |
| 52 | + | |
| 53 | +2. Install additional dependencies | |
| 54 | + | |
| 55 | + ```shell | |
| 56 | + $ brew install adwaita-icon-theme imagemagick | |
| 57 | + ``` | |
| 58 | + | |
| 59 | +3. Configure and build | |
| 60 | + | |
| 61 | + ```shell | |
| 62 | + $ ./autogen.sh | |
| 63 | + $ make all | |
| 64 | + ```` | |
| 65 | + | |
| 66 | +4. Create app bundle | |
| 67 | + | |
| 68 | + ```shell | |
| 69 | + $ cd macos | |
| 70 | + $ ./bundle | ... | ... |
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| 3 | +<plist version="1.0"> | |
| 4 | +<dict> | |
| 5 | + <key>CFBundleExecutable</key> | |
| 6 | + <string>launcher.sh</string> | |
| 7 | + <key>CFBundleName</key> | |
| 8 | + <string>pw3270</string> | |
| 9 | + <key>CFBundleDisplayName</key> | |
| 10 | + <string>pw3270</string> | |
| 11 | + <key>CFBundleIconFile</key> | |
| 12 | + <string>pw3270.icns</string> | |
| 13 | + <key>CFBundleIdentifier</key> | |
| 14 | + <string>br.com.bb.pw3270</string> | |
| 15 | + <key>NSHighResolutionCapable</key> | |
| 16 | + <true/> | |
| 17 | + <key>LSMinimumSystemVersion</key> | |
| 18 | + <string>10.13.6</string> | |
| 19 | +</dict> | |
| 20 | +</plist> | ... | ... |
| ... | ... | @@ -0,0 +1,210 @@ |
| 1 | +#!/usr/bin/env bash | |
| 2 | +#@author André Breves <andre.breves@gmail.com> | |
| 3 | +set -Eeuo pipefail | |
| 4 | + | |
| 5 | +check_dependencies() { | |
| 6 | + local unavailable=() | |
| 7 | + for dependency in "${@:-$(</dev/stdin)}"; do | |
| 8 | + if [[ ! -x "$(command -v ${dependency})" ]]; then unavailable+=("${dependency}"); fi | |
| 9 | + done | |
| 10 | + if [[ ${#unavailable[@]} == 1 ]]; then | |
| 11 | + echo "Dependency '${unavailable[*]}' not found." | |
| 12 | + exit 1 | |
| 13 | + elif [[ ${#unavailable[@]} -gt 1 ]]; then | |
| 14 | + error "Dependencies '${unavailable[*]}' not found." | |
| 15 | + exit 1 | |
| 16 | + fi | |
| 17 | +} | |
| 18 | + | |
| 19 | +find_lib() { | |
| 20 | + # https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/UsingDynamicLibraries.html | |
| 21 | + local libs_path="${HOME}/lib /usr/local/lib /usr/lib" | |
| 22 | + for lib in "${@:-$(</dev/stdin)}"; do | |
| 23 | + local found="" | |
| 24 | + if [[ -f "${lib}" ]]; then | |
| 25 | + found="$(greadlink -m "${lib}")" | |
| 26 | + else | |
| 27 | + for path in ${libs_path}; do | |
| 28 | + if [[ -f "${path}/${lib}" ]]; then | |
| 29 | + found="$(greadlink -m "${path}/${lib}")" | |
| 30 | + break | |
| 31 | + fi | |
| 32 | + done | |
| 33 | + fi | |
| 34 | + if [[ "${found}" != "" ]]; then | |
| 35 | + echo "${found}" | |
| 36 | + else | |
| 37 | + echo >&2 "Lib ${lib} not found" | |
| 38 | + exit 1 | |
| 39 | + fi | |
| 40 | + done | |
| 41 | +} | |
| 42 | + | |
| 43 | +bundle_cp() { | |
| 44 | + local system_libs='^(/System/.*|/usr/lib/.*)$' | |
| 45 | + | |
| 46 | + for source in "${@:-$(</dev/stdin)}"; do | |
| 47 | + source="$(greadlink -m "${source}")" | |
| 48 | + | |
| 49 | + if [[ "${source}" =~ ${system_libs} ]]; then continue; fi | |
| 50 | + | |
| 51 | + if [[ ! -f "${source}" ]]; then | |
| 52 | + echo >&2 "File \"${source}\" not found" | |
| 53 | + exit 1 | |
| 54 | + fi | |
| 55 | + | |
| 56 | + local id="" | |
| 57 | + local target="" | |
| 58 | + local file_type | |
| 59 | + file_type="$(file -b "${source}")" | |
| 60 | + case "${file_type}" in | |
| 61 | + *executable*) | |
| 62 | + target="$(greadlink -m "${exe_path}/$(basename "${source}")")";; | |
| 63 | + *) | |
| 64 | + id="@rpath/$(basename "${source}")" | |
| 65 | + target="$(greadlink -m "${lib_path}/$(basename "${source}")")";; | |
| 66 | + esac | |
| 67 | + | |
| 68 | + if [[ "${id}" != "" ]]; then echo "${id}"; fi | |
| 69 | + | |
| 70 | + if [[ -f "${target}" ]]; then continue; fi | |
| 71 | + | |
| 72 | + mkdir -p "$(dirname "${target}")" | |
| 73 | + cp "${source}" "${target}" | |
| 74 | + chmod u+w "${target}" | |
| 75 | + | |
| 76 | + if [[ "${id}" != "" ]]; then install_name_tool -id "${id}" "${target}"; fi | |
| 77 | + install_name_tool -add_rpath "@executable_path/../Frameworks" "${target}" | |
| 78 | + | |
| 79 | + for old_install_name in $(otool -L "${target}" | grep '^\t' | cut -c 2- | sed -n "s/\(.*\) (.*)/\1/p"); do | |
| 80 | + if [[ "${old_install_name}" == "${id}" ]]; then continue; fi | |
| 81 | + local lib="$(find_lib "${old_install_name}")" | |
| 82 | + local new_install_name="$(bundle_cp "${lib}")" | |
| 83 | + if [[ "${new_install_name}" != "" ]]; then | |
| 84 | + install_name_tool -change "${old_install_name}" "${new_install_name}" "${target}" | |
| 85 | + fi | |
| 86 | + done | |
| 87 | + echo >&2 "${target}" | |
| 88 | + done | |
| 89 | +} | |
| 90 | + | |
| 91 | +bundle_cache() { | |
| 92 | + local awaiting_file=1; | |
| 93 | + while IFS= read -r line; do | |
| 94 | + if (( awaiting_file )); then | |
| 95 | + if [[ ! "${line}" =~ ^"#" && "${line}" != "" ]]; then | |
| 96 | + line="${line##\ }" | |
| 97 | + line="${line#\"}" | |
| 98 | + line="${line%%\ }" | |
| 99 | + line="${line%\"}" | |
| 100 | + line="\"$(bundle_cp "${line}")\"" | |
| 101 | + awaiting_file=0 | |
| 102 | + fi | |
| 103 | + else | |
| 104 | + if [[ "${line}" == "" ]]; then | |
| 105 | + awaiting_file=1 | |
| 106 | + fi | |
| 107 | + fi | |
| 108 | + printf '%s\n' "${line}" | |
| 109 | + done | |
| 110 | +} | |
| 111 | + | |
| 112 | +# Check dependencies | |
| 113 | +check_dependencies otool grep cut sed greadlink qlmanage sips iconutil | |
| 114 | + | |
| 115 | +# Creates temporary directory | |
| 116 | +echo "Creating temporary directory" | |
| 117 | +tmp="$(mktemp -d)" | |
| 118 | +trap 'echo "Removing temporary directory \"${tmp}\""; rm -rf "${tmp}"' EXIT | |
| 119 | + | |
| 120 | +bundle="pw3270.app" | |
| 121 | +bundle_path="${bundle}/Contents" | |
| 122 | +exe_path="${bundle_path}/MacOS" | |
| 123 | +lib_path="${bundle_path}/Frameworks" | |
| 124 | +res_path="${bundle_path}/Resources" | |
| 125 | + | |
| 126 | +rm -fr "${bundle}" | |
| 127 | + | |
| 128 | +mkdir -p "${bundle_path}" | |
| 129 | +cp "Info.plist" "${bundle_path}" | |
| 130 | + | |
| 131 | +mkdir -p "${res_path}" | |
| 132 | +cp -r "../ui" "${res_path}" | |
| 133 | +cp -r "$(brew --prefix)/share/pw3270/remap" "${res_path}" | |
| 134 | +cp "$(brew --prefix)/share/pw3270/colors.conf" "${res_path}" | |
| 135 | + | |
| 136 | +# Bundle GLib schemas | |
| 137 | +echo "Bundling GLib schemas" | |
| 138 | +mkdir -p "${tmp}/schemas" | |
| 139 | +cp "../schemas/linux/"*".xml" "${tmp}/schemas" | |
| 140 | +cp "$(pkg-config gtk+-3.0 --variable=prefix)/share/glib-2.0/schemas/org.gtk.Settings."*".gschema.xml" "${tmp}/schemas" | |
| 141 | +glib-compile-schemas --targetdir="${res_path}" "${tmp}/schemas" | |
| 142 | + | |
| 143 | +# Create the GTK settings file | |
| 144 | +# https://developer.gnome.org/gtk3/stable/GtkSettings.html | |
| 145 | +mkdir -p "${res_path}/gtk-3.0" | |
| 146 | +cat > "${res_path}/gtk-3.0/settings.ini" << EOF | |
| 147 | +[Settings] | |
| 148 | +gtk-theme-name=Adwaita | |
| 149 | +gtk-print-preview-command="open -b com.apple.Preview %f" | |
| 150 | +EOF | |
| 151 | + | |
| 152 | +# Make icon bundle | |
| 153 | +echo "Creating app icon bundle" | |
| 154 | +iconset="${tmp}/pw3270.iconset" | |
| 155 | +rm -fr "${iconset}" | |
| 156 | +mkdir -p "${iconset}" | |
| 157 | +icon_sizes=("16" "32" "64" "128" "256" "512" "1024") | |
| 158 | +for ((i=1; i < ${#icon_sizes[*]}; i++)); do | |
| 159 | + size=${icon_sizes[$((i - 1))]} | |
| 160 | + convert -density "${size}" -resize "${size}x" -background transparent "../branding/pw3270.svg" "${iconset}/icon_${size}x${size}.png" | |
| 161 | + | |
| 162 | + size2x=${icon_sizes[${i}]} | |
| 163 | + convert -density "${size2x}" -resize "${size2x}x" -background transparent "../branding/pw3270.svg" "${iconset}/icon_${size}x${size}@2x.png" | |
| 164 | +done | |
| 165 | +iconutil -c icns -o "${res_path}/pw3270.icns" "${iconset}" | |
| 166 | + | |
| 167 | + | |
| 168 | +# Copy icons | |
| 169 | +mkdir -p "${res_path}/icons" | |
| 170 | +cp -r "$(brew --prefix adwaita-icon-theme)/share/icons/" "${res_path}/icons" | |
| 171 | +cp -r "$(brew --prefix hicolor-icon-theme)/share/icons/" "${res_path}/icons" | |
| 172 | +mogrify -format png -path "${res_path}" -background transparent "../branding/*.svg" | |
| 173 | + | |
| 174 | +# Copy themes | |
| 175 | +mkdir -p "${res_path}/themes" | |
| 176 | +cp -a "$(brew --prefix gtk+3)/share/themes/Mac" "${res_path}/themes" | |
| 177 | + | |
| 178 | +# Copy mime database | |
| 179 | +mkdir -p "${res_path}/mime" | |
| 180 | +cp "$(pkg-config shared-mime-info --variable=prefix)/share/mime/mime.cache" "${res_path}/mime" | |
| 181 | + | |
| 182 | +# Copy executables | |
| 183 | +mkdir -p "${exe_path}" | |
| 184 | +bundle_cp "../.bin/Release/pw3270" | |
| 185 | +cp "launcher.sh" "${exe_path}" | |
| 186 | + | |
| 187 | +# Bundle GdkPixbuf Image Loader Modules | |
| 188 | +gdk-pixbuf-query-loaders | bundle_cache > "${res_path}/gdk-loaders.cache" | |
| 189 | + | |
| 190 | +# Bundle GTK+ Input Method Modules | |
| 191 | +gtk_prefix="$(pkg-config gtk+-3.0 --variable prefix)" | |
| 192 | +gtk-query-immodules-3.0 | bundle_cache \ | |
| 193 | + | sed "s|${gtk_prefix}/share/locale|@executable_path/../Resources/locale|g" \ | |
| 194 | + > "${res_path}/gtk.immodules" | |
| 195 | + | |
| 196 | +# Bundle print backends | |
| 197 | +mkdir -p "${lib_path}/printbackends" | |
| 198 | +for backend in "$(pkg-config gtk+-3.0 --variable=prefix)/lib/gtk-3.0/$(pkg-config gtk+-3.0 --variable=gtk_binary_version)/printbackends/"*.so; do | |
| 199 | + bundle_cp "${backend}" | |
| 200 | + # TODO: update bundle_cp to inform destiny dir | |
| 201 | + mv "${lib_path}/$(basename "${backend}")" "${lib_path}/printbackends" | |
| 202 | +done | |
| 203 | + | |
| 204 | +# TODO: gerar o Info.plist com a versão do macOS $(sw_vers -productVersion) | |
| 205 | + | |
| 206 | +# Bundle locale | |
| 207 | +mkdir -p "${res_path}/locale" | |
| 208 | +cp -r "../.bin/locale/" "${res_path}/locale" | |
| 209 | +cp "$(brew --prefix)/share/locale/pt_BR/LC_MESSAGES/lib3270.mo" "${res_path}/locale/pt_BR/LC_MESSAGES" | |
| 210 | +cp "$(brew --prefix)/share/locale/pt_BR/LC_MESSAGES/libv3270.mo" "${res_path}/locale/pt_BR/LC_MESSAGES" | ... | ... |
| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | +#!/usr/bin/env sh | |
| 2 | +#@author André Breves <andre.breves@gmail.com> | |
| 3 | +set -euo | |
| 4 | + | |
| 5 | +cd "${0%/*}" | |
| 6 | +executable_path="${PWD}" | |
| 7 | +cd .. | |
| 8 | +contents_path="${PWD}" | |
| 9 | +cd Resources | |
| 10 | +resource_path="${PWD}" | |
| 11 | + | |
| 12 | +info_plist="${contents_path}/Info.plist" | |
| 13 | +bundle_identifier=$(plutil -extract "CFBundleIdentifier" xml1 -o - "${info_plist}" | sed -n "s/.*<string>\(.*\)<\/string>.*/\1/p") | |
| 14 | + | |
| 15 | +# XDG Base Directory Specification | |
| 16 | +# https://specifications.freedesktop.org/basedir-spec/latest/ar01s03.html | |
| 17 | + | |
| 18 | +# Defines the base directory relative to which user specific configuration files should be stored | |
| 19 | +export XDG_CONFIG_HOME="${HOME}/Library/Application Support/${bundle_identifier}" | |
| 20 | + | |
| 21 | +# Defines the base directory relative to which user specific data files should be stored | |
| 22 | +export XDG_DATA_HOME="${HOME}/Library/Application Support/${bundle_identifier}" | |
| 23 | + | |
| 24 | +# Defines the preference-ordered set of base directories to search for data files in addition to the $XDG_DATA_HOME base directory | |
| 25 | +export XDG_DATA_DIRS="${resource_path}" | |
| 26 | + | |
| 27 | +# Defines the preference-ordered set of base directories to search for configuration files in addition to the $XDG_CONFIG_HOME base directory | |
| 28 | +export XDG_CONFIG_DIRS="${resource_path}" | |
| 29 | + | |
| 30 | +# Defines the base directory relative to which user specific non-essential data files should be stored | |
| 31 | +export XDG_CACHE_HOME="${HOME}/Library/Caches/${bundle_identifier}" | |
| 32 | + | |
| 33 | + | |
| 34 | +# Running GTK+ Applications | |
| 35 | +# https://developer.gnome.org/gtk3/stable/gtk-running.html | |
| 36 | + | |
| 37 | +# If set, makes GTK+ use $GTK_DATA_PREFIX instead of the prefix configured when GTK+ was compiled | |
| 38 | +export GTK_DATA_PREFIX="${resource_path}" | |
| 39 | + | |
| 40 | +# Specifies the file listing the Input Method modules to load | |
| 41 | +export GTK_IM_MODULE_FILE="${resource_path}/gtk.immodules" | |
| 42 | + | |
| 43 | +# Specifies the file listing the GdkPixbuf loader modules to load | |
| 44 | +export GDK_PIXBUF_MODULE_FILE="${resource_path}/gdk-loaders.cache" | |
| 45 | + | |
| 46 | +# Specifies a list of directories to search when GTK+ is looking for dynamically loaded objects such as the modules | |
| 47 | +# specified by GTK_MODULES, theme engines, input method modules, file system backends and print backends. | |
| 48 | +export GTK_PATH="${contents_path}/Frameworks" | |
| 49 | + | |
| 50 | +# Running GIO applications | |
| 51 | +# https://developer.gnome.org/gio/stable/running-gio-apps.html | |
| 52 | + | |
| 53 | +# This variable can be set to the names of directories to consider when looking for compiled schemas for GSettings | |
| 54 | +export GSETTINGS_SCHEMA_DIR="${resource_path}" | |
| 55 | + | |
| 56 | +# export LANG="pt_BR" | |
| 57 | +# export LC_MESSAGES="pt_BR" | |
| 58 | +# export LC_ALL="pt_BR" | |
| 59 | + | |
| 60 | +mkdir -p "${XDG_CONFIG_HOME}" | |
| 61 | +mkdir -p "${XDG_DATA_HOME}" | |
| 62 | +mkdir -p "${XDG_CACHE_HOME}" | |
| 63 | + | |
| 64 | +cd "${resource_path}" | |
| 65 | +exec "${executable_path}/pw3270" | ... | ... |
src/objects/application/actions/about.c
| ... | ... | @@ -36,6 +36,9 @@ |
| 36 | 36 | static const gchar *authors[] = |
| 37 | 37 | { |
| 38 | 38 | "Perry Werneck <perry.werneck@gmail.com>", |
| 39 | + #ifdef __APPLE__ | |
| 40 | + "Andre Breves <andre.breves@gmail.com>", | |
| 41 | + #endif | |
| 39 | 42 | "Paul Mattes <Paul.Mattes@usa.net>", |
| 40 | 43 | "Georgia Tech Research Corporation (GTRC)", |
| 41 | 44 | "and others", | ... | ... |
src/pw3270/dialog.c
| ... | ... | @@ -73,6 +73,9 @@ |
| 73 | 73 | static const gchar *authors[] = |
| 74 | 74 | { |
| 75 | 75 | "Perry Werneck <perry.werneck@gmail.com>", |
| 76 | + #ifdef __APPLE__ | |
| 77 | + "Andre Breves <andre.breves@gmail.com>", | |
| 78 | + #endif | |
| 76 | 79 | "Paul Mattes <Paul.Mattes@usa.net>", |
| 77 | 80 | "Georgia Tech Research Corporation (GTRC)", |
| 78 | 81 | "and others", | ... | ... |