|
| 1 | +#!/bin/bash |
| 2 | +# Script to build QGIS inside the qgis-build-deps-mingw.dockerfile Docker container |
| 3 | +# Run from QGIS root dirctory with: |
| 4 | +# docker run --rm -w /QGIS -v $(pwd):/QGIS elpaso/qgis-deps-mingw:latest /QGIS/ms-windows/mingw/build.sh |
| 5 | + |
| 6 | + |
| 7 | +#!/bin/sh |
| 8 | + |
| 9 | +ARCH=${1:-x86_64} |
| 10 | +DEBUG=false |
| 11 | +if [ "$2" == "DEBUG" ]; then |
| 12 | + DEBUG=true |
| 13 | +fi |
| 14 | +NJOBS=${3:-$(($(grep -c ^processor /proc/cpuinfo) * 3 / 2))} |
| 15 | + |
| 16 | + |
| 17 | +if [ "$ARCH" == "i686" ]; then |
| 18 | + bits=32 |
| 19 | +elif [ "$ARCH" == "x86_64" ]; then |
| 20 | + bits=64 |
| 21 | +else |
| 22 | + echo "Error: unrecognized ARCHitecture $ARCH" |
| 23 | + exit 1 |
| 24 | +fi |
| 25 | + |
| 26 | +# Do copies instead of links if building inside container |
| 27 | +if [ -f /.dockerenv ]; then |
| 28 | + lnk() { |
| 29 | + cp -aL "$1" "$2" |
| 30 | + } |
| 31 | +else |
| 32 | + lnk() { |
| 33 | + ln -sf "$1" "$2" |
| 34 | + } |
| 35 | +fi |
| 36 | + |
| 37 | +# Note: This script is written to be used with the Fedora mingw environment |
| 38 | +MINGWROOT=/usr/$ARCH-w64-mingw32/sys-root/mingw |
| 39 | + |
| 40 | +if $DEBUG; then |
| 41 | + OPTFLAGS="-O0 -g1 -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -fno-omit-frame-pointer" |
| 42 | + buildtype="DEBUG" |
| 43 | +else |
| 44 | + OPTFLAGS="-O2 -g1 -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -fno-omit-frame-pointer" |
| 45 | + buildtype="RelWithDEBUGInfo" |
| 46 | +fi |
| 47 | +pyver=$(mingw${bits}-python3 -c "import sys; print('.'.join(list(map(str, sys.version_info))[0:2]))") |
| 48 | + |
| 49 | +# Halt on errors |
| 50 | +set -e |
| 51 | + |
| 52 | +export MINGW32_CFLAGS="$OPTFLAGS" |
| 53 | +export MINGW32_CXXFLAGS="$OPTFLAGS" |
| 54 | +export MINGW64_CFLAGS="$OPTFLAGS" |
| 55 | +export MINGW64_CXXFLAGS="$OPTFLAGS" |
| 56 | + |
| 57 | +SRCDIR="$(readlink -f "$(dirname "$(readlink -f "$0")")/../..")" |
| 58 | +if $DEBUG; then |
| 59 | + BUILDDIR="$SRCDIR/build_mingw${bits}_DEBUG" |
| 60 | +else |
| 61 | + BUILDDIR="$SRCDIR/build_mingw${bits}" |
| 62 | +fi |
| 63 | +installroot="$BUILDDIR/dist" |
| 64 | +installprefix="$installroot/usr/$ARCH-w64-mingw32/sys-root/mingw" |
| 65 | + |
| 66 | +# Cleanup |
| 67 | +rm -rf "$installroot" |
| 68 | + |
| 69 | +# Build |
| 70 | +mkdir -p $BUILDDIR |
| 71 | +( |
| 72 | + cd $BUILDDIR |
| 73 | + qsci_ver=$(grep -Eo '\s*([0-9]+\.[0-9]+\.[0-9]+)' $MINGWROOT/include/qt5/Qsci/qsciglobal.h) |
| 74 | + mingw$bits-cmake \ |
| 75 | + -DCMAKE_CROSS_COMPILING=1 \ |
| 76 | + -DCMAKE_BUILD_TYPE=$buildtype \ |
| 77 | + -DNATIVE_CRSSYNC_BIN=$(readlink -f $SRCDIR)/build/output/bin/crssync \ |
| 78 | + -DQSCINTILLA_VERSION_STR=$qsci_ver \ |
| 79 | + -DQSCINTILLA_LIBRARY=$MINGWROOT/lib/libqscintilla2_qt5.dll.a \ |
| 80 | + -DQSCI_MOD_VERSION_STR=$qsci_ver \ |
| 81 | + -DQWT_INCLUDE_DIR=$MINGWROOT/include/qt5/qwt \ |
| 82 | + -DQSCI_SIP_DIR=$MINGWROOT/share/sip/PyQt5/Qsci/ \ |
| 83 | + -DBUILD_TESTING=OFF \ |
| 84 | + -DZSTD_INCLUDE_DIR=/usr/x86_64-w64-mingw32/sys-root/mingw/include/zstd/ \ |
| 85 | + -DENABLE_TESTS=OFF \ |
| 86 | + -DQGIS_BIN_SUBDIR=bin \ |
| 87 | + -DQGIS_CGIBIN_SUBDIR=bin \ |
| 88 | + -DQGIS_LIB_SUBDIR=lib \ |
| 89 | + -DQGIS_LIBEXEC_SUBDIR=lib/qgis \ |
| 90 | + -DQGIS_DATA_SUBDIR=share/qgis \ |
| 91 | + -DQGIS_PLUGIN_SUBDIR=lib/qgis/plugins \ |
| 92 | + -DQGIS_INCLUDE_SUBDIR=include/qgis \ |
| 93 | + -DQGIS_SERVER_MODULE_SUBDIR=lib/qgis/server \ |
| 94 | + -DQGIS_QML_SUBDIR=lib/qt5/qml \ |
| 95 | + -DBINDINGS_GLOBAL_INSTALL=ON \ |
| 96 | + -DWITH_SERVER=OFF \ |
| 97 | + -DTXT2TAGS_EXECUTABLE= \ |
| 98 | + .. |
| 99 | +) |
| 100 | + |
| 101 | +# Compile native crssync |
| 102 | +# mkdir -p $BUILDDIR/native_crssync |
| 103 | +# ( |
| 104 | +# cd $BUILDDIR/native_crssync |
| 105 | +# echo "Building native crssync..." |
| 106 | +# moc-qt5 $SRCDIR/src/core/qgsapplication.h > moc_qgsapplication.cpp |
| 107 | +# g++ $OPTFLAGS -fPIC -o crssync $SRCDIR/src/crssync/main.cpp $SRCDIR/src/crssync/qgscrssync.cpp moc_qgsapplication.cpp $SRCDIR/src/core/qgsapplication.cpp -DCORE_EXPORT= -DCOMPILING_CRSSYNC -I$SRCDIR/src/core/ -I$SRCDIR/src/core/geometry -I$BUILDDIR $(pkg-config --cflags --libs Qt5Widgets gdal sqlite3 proj) |
| 108 | +# ) |
| 109 | +# crssync needs X at runtime |
| 110 | +# Xvfb :99 & |
| 111 | +# export DISPLAY=:99 |
| 112 | + |
| 113 | +mingw$bits-make -C$BUILDDIR -j$NJOBS DESTDIR="${installroot}" install VERBOSE=1 |
| 114 | + |
| 115 | +# Remove plugins with missing dependencies |
| 116 | +rm -rf ${installroot}/share/qgis/python/plugins/{MetaSeARCH,processing} |
| 117 | + |
| 118 | +# Strip DEBUGinfo |
| 119 | +binaries=$(find $installprefix -name '*.exe' -or -name '*.dll' -or -name '*.pyd') |
| 120 | +for f in $binaries |
| 121 | +do |
| 122 | + case $(mingw-objdump -h $f 2>/dev/null | egrep -o '(DEBUG[\.a-z_]*|gnu.version)') in |
| 123 | + *DEBUGlink*) continue ;; |
| 124 | + *DEBUG*) ;; |
| 125 | + *gnu.version*) |
| 126 | + echo "WARNING: $(basename $f) is already stripped!" |
| 127 | + continue |
| 128 | + ;; |
| 129 | + *) continue ;; |
| 130 | + esac |
| 131 | + |
| 132 | + echo extracting DEBUG info from $f |
| 133 | + mingw-objcopy --only-keep-DEBUG $f $f.DEBUG || : |
| 134 | + pushd $(dirname $f) |
| 135 | + keep_symbols=`mktemp` |
| 136 | + mingw-nm $f.DEBUG --format=sysv --defined-only | awk -F \| '{ if ($4 ~ "Function") print $1 }' | sort > "$keep_symbols" |
| 137 | + mingw-objcopy --add-gnu-DEBUGlink=`basename $f.DEBUG` --strip-unneeded `basename $f` --keep-symbols="$keep_symbols" || : |
| 138 | + rm -f "$keep_symbols" |
| 139 | + popd |
| 140 | +done |
| 141 | + |
| 142 | +# Collect dependencies |
| 143 | +function isnativedll { |
| 144 | + # If the import library exists but not the dynamic library, the dll ist most likely a native one |
| 145 | + local lower=${1,,} |
| 146 | + [ ! -e $MINGWROOT/bin/$1 ] && [ -f $MINGWROOT/lib/lib${lower/%.*/.a} ] && return 0; |
| 147 | + return 1; |
| 148 | +} |
| 149 | + |
| 150 | +function linkDep { |
| 151 | +# Link the specified binary dependency and it's dependencies |
| 152 | + local indent=$3 |
| 153 | + local destdir="$installprefix/${2:-bin}" |
| 154 | + local name="$(basename $1)" |
| 155 | + test -e "$destdir/$name" && return 0 |
| 156 | + test -e "$destdir/qgisplugins/$name" && return 0 |
| 157 | + echo "${indent}${1}" |
| 158 | + [ ! -e "$MINGWROOT/$1" ] && echo "Error: missing $MINGWROOT/$1" && return 1 |
| 159 | + mkdir -p "$destdir" || return 1 |
| 160 | + lnk "$MINGWROOT/$1" "$destdir/$name" || return 1 |
| 161 | + echo "${2:-bin}/$name: $(rpm -qf "$MINGWROOT/$1")" >> $installprefix/origins.txt |
| 162 | + autoLinkDeps "$destdir/$name" "${indent} " || return 1 |
| 163 | + [ -e "$MINGWROOT/$1.DEBUG" ] && lnk "$MINGWROOT/$1.DEBUG" "$destdir/$name.DEBUG" || ($DEBUG && echo "Warning: missing $name.DEBUG" || :) |
| 164 | + return 0 |
| 165 | +} |
| 166 | + |
| 167 | +function autoLinkDeps { |
| 168 | +# Collects and links the dependencies of the specified binary |
| 169 | + for dep in $(mingw-objdump -p "$1" | grep "DLL Name" | awk '{print $3}'); do |
| 170 | + if ! isnativedll "$dep"; then |
| 171 | + # HACK fix incorrect libpq case |
| 172 | + dep=${dep/LIBPQ/libpq} |
| 173 | + linkDep bin/$dep bin "$2" || return 1 |
| 174 | + fi |
| 175 | + done |
| 176 | + return 0 |
| 177 | +} |
| 178 | + |
| 179 | +# Install python libs |
| 180 | +( |
| 181 | +cd $MINGWROOT |
| 182 | +SAVEIFS=$IFS |
| 183 | +IFS=$(echo -en "\n\b") |
| 184 | +for file in $(find lib/python${pyver} -type f); do |
| 185 | + mkdir -p "$installprefix/$(dirname $file)" |
| 186 | + lnk "$MINGWROOT/$file" "$installprefix/$file" |
| 187 | +done |
| 188 | +IFS=$SAVEIFS |
| 189 | +) |
| 190 | + |
| 191 | +echo "Linking dependencies..." |
| 192 | +binaries=$(find $installprefix -name '*.exe' -or -name '*.dll' -or -name '*.pyd') |
| 193 | +for binary in $binaries; do |
| 194 | + autoLinkDeps $binary |
| 195 | +done |
| 196 | +linkDep bin/gdb.exe |
| 197 | +linkDep bin/python3.exe |
| 198 | +linkDep bin/python3w.exe |
| 199 | + |
| 200 | +linkDep $(ls $MINGWROOT/bin/libssl-*.dll | sed "s|$MINGWROOT/||") |
| 201 | +linkDep $(ls $MINGWROOT/bin/libcrypto-*.dll | sed "s|$MINGWROOT/||") |
| 202 | +linkDep lib/mod_spatialite.dll bin |
| 203 | + |
| 204 | +# Additional dependencies |
| 205 | +linkDep lib/qt5/plugins/imageformats/qgif.dll bin/imageformats |
| 206 | +linkDep lib/qt5/plugins/imageformats/qicns.dll bin/imageformats |
| 207 | +linkDep lib/qt5/plugins/imageformats/qico.dll bin/imageformats |
| 208 | +linkDep lib/qt5/plugins/imageformats/qjp2.dll bin/imageformats |
| 209 | +linkDep lib/qt5/plugins/imageformats/qjpeg.dll bin/imageformats |
| 210 | +linkDep lib/qt5/plugins/imageformats/qtga.dll bin/imageformats |
| 211 | +linkDep lib/qt5/plugins/imageformats/qtiff.dll bin/imageformats |
| 212 | +linkDep lib/qt5/plugins/imageformats/qwbmp.dll bin/imageformats |
| 213 | +linkDep lib/qt5/plugins/imageformats/qwebp.dll bin/imageformats |
| 214 | +linkDep lib/qt5/plugins/imageformats/qsvg.dll bin/imageformats |
| 215 | +linkDep lib/qt5/plugins/platforms/qwindows.dll bin/platforms |
| 216 | +linkDep lib/qt5/plugins/printsupport/windowsprintersupport.dll bin/printsupport |
| 217 | +linkDep lib/qt5/plugins/styles/qwindowsvistastyle.dll bin/styles |
| 218 | +linkDep lib/qt5/plugins/audio/qtaudio_windows.dll bin/audio |
| 219 | +linkDep lib/qt5/plugins/mediaservice/dsengine.dll bin/mediaservice |
| 220 | +linkDep lib/qt5/plugins/mediaservice/qtmedia_audioengine.dll bin/mediaservice |
| 221 | +linkDep lib/qt5/plugins/sqldrivers/qsqlite.dll bin/sqldrivers |
| 222 | +linkDep lib/qt5/plugins/sqldrivers/qsqlodbc.dll bin/sqldrivers |
| 223 | +linkDep lib/qt5/plugins/sqldrivers/qsqlpsql.dll bin/sqldrivers |
| 224 | + |
| 225 | +linkDep lib/qt5/plugins/crypto/libqca-gcrypt.dll bin/crypto |
| 226 | +linkDep lib/qt5/plugins/crypto/libqca-logger.dll bin/crypto |
| 227 | +linkDep lib/qt5/plugins/crypto/libqca-softstore.dll bin/crypto |
| 228 | +linkDep lib/qt5/plugins/crypto/libqca-gnupg.dll bin/crypto |
| 229 | +linkDep lib/qt5/plugins/crypto/libqca-ossl.dll bin/crypto |
| 230 | + |
| 231 | +mkdir -p $installprefix/share/qt5/translations/ |
| 232 | +cp -a $MINGWROOT/share/qt5/translations/qt_*.qm $installprefix/share/qt5/translations |
| 233 | +cp -a $MINGWROOT/share/qt5/translations/qtbase_*.qm $installprefix/share/qt5/translations |
| 234 | + |
| 235 | +# Data files |
| 236 | +mkdir -p $installprefix/share/ |
| 237 | +cp -a /usr/share/gdal $installprefix/share/gdal |
| 238 | +cp -a /usr/share/proj $installprefix/share/proj |
| 239 | + |
| 240 | +# Sort origins file |
| 241 | +cat $installprefix/origins.txt | sort | uniq > $installprefix/origins.new && mv $installprefix/origins.new $installprefix/origins.txt |
| 242 | + |
| 243 | +# Create package |
| 244 | +DISTROOT=build_mingw64/dist/usr/x86_64-w64-mingw32/sys-root/mingw |
| 245 | +DEBUGROOT=dist_DEBUG |
| 246 | +for file in $(find $DISTROOT -name '*.DEBUG' \( -type l -or -type f \)); do |
| 247 | + dest=${file/$DISTROOT/$DEBUGROOT} |
| 248 | + mkdir -p "$(dirname $dest)" |
| 249 | + sudo mv "$file" "$dest" |
| 250 | +done |
| 251 | + |
| 252 | +sudo mv $DISTROOT QGIS-Portable |
| 253 | +zip -r qgis-portable-win64.zip QGIS-Portable |
| 254 | +(cd $DEBUGROOT && zip -r - *) > qgis-portable-win64-debugsym.zip |
| 255 | + |
0 commit comments