Skip to content

Commit 1dd6db3

Browse files
committed
[mxe] Add install instructions for mxe
1 parent d19eef0 commit 1dd6db3

File tree

4 files changed

+382
-0
lines changed

4 files changed

+382
-0
lines changed

INSTALL

+35
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Last Change : Friday February 02, 2018
2323
4.1. Building with Microsoft Visual Studio
2424
4.2. Building using MinGW
2525
4.3. Creation of MSYS environment for compilation of QGIS
26+
4.4 Building on Linux with mxe
2627
5. Building on MacOS X
2728
5.1. Install Developer Tools
2829
5.2. Install Qt4 from disk image
@@ -1027,6 +1028,40 @@ We're done with preparation of MSYS environment. Now you can delete all stuff in
10271028
of space and it's not necessary at all.
10281029

10291030

1031+
1032+
4.4. Building on Linux with mxe
1033+
===============================
1034+
1035+
With this approach you can build a windows binary on Linux using mxe MXE (M cross environment).
1036+
You can find the build script and a README file in the ms-windows/mxe directory.
1037+
1038+
For now, Python buildings cannot be built with mxe.
1039+
1040+
4.4.1. Initial setup
1041+
====================
1042+
1043+
Please follow the instructions on mxe website to setup your building toolchain http://mxe.cc/,
1044+
take note of the path where you have installed mxe.
1045+
1046+
4.4.2. Building the dependencies
1047+
================================
1048+
1049+
Please see the README under ms-windows/mxe for a list of the dependencies that needs to be
1050+
build in mxe before attempting to build QGIS.
1051+
1052+
1053+
4.4.3. Cross-Building QGIS
1054+
==========================
1055+
1056+
Edit the build-mxe.sh script and change the path where your mxe installation is located, you
1057+
can also change the build and release directory.
1058+
1059+
4.4.4. Testing QGIS
1060+
====================
1061+
1062+
Copy and unzip the release package ona a Windows machine and launch it!
1063+
1064+
10301065
5. Building on MacOS X
10311066
======================
10321067

ms-windows/mxe/README

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
2+
Scripts to cross build a windows QGIS binary from Linux using MXE:
3+
(M cross environment) http://mxe.cc/
4+
5+
For now, Python bindings cannot be built with mxe.
6+
7+
Follow the instructions on the website to prepare the mxe environment, you
8+
will need to build all required dependencies for QGIS.
9+
10+
Note that someof the packages listed below are dependencies of other
11+
packages, you will probably not need to build them all explicitely.
12+
13+
14+
armadillo
15+
bfd
16+
bzip2
17+
cairo
18+
cmake
19+
curl
20+
dbus
21+
dlfcn-win32
22+
expat
23+
fontconfig
24+
freetds
25+
freetype
26+
freexl
27+
gcc
28+
gdal
29+
gendef
30+
geos
31+
gettext
32+
giflib
33+
glib
34+
gmp
35+
gnutls
36+
gsl
37+
gta
38+
harfbuzz
39+
hdf4
40+
hdf5
41+
icu4c
42+
isl
43+
jasper
44+
jpeg
45+
json-c
46+
lcms
47+
libffi
48+
libgcrypt
49+
libgeotiff
50+
libgnurx
51+
libgpg_error
52+
libiconv
53+
libidn2
54+
libmng
55+
libmysqlclient
56+
libpng
57+
libspatialindex
58+
libssh2
59+
libunistring
60+
libwebp
61+
libxml2
62+
libzip
63+
lzo
64+
mpc
65+
mpfr
66+
netcdf
67+
nettle
68+
openblas
69+
openjpeg
70+
openssl
71+
pcre
72+
pcre2
73+
pixman
74+
pkgconf
75+
portablexdr
76+
postgresql
77+
proj
78+
qca
79+
qscintilla2
80+
qt3d
81+
qtactiveqt
82+
qtbase
83+
qtcanvas3d
84+
qtcharts
85+
qtconnectivity
86+
qtdatavis3d
87+
qtdeclarative
88+
qtgamepad
89+
qtgraphicaleffects
90+
qtimageformats
91+
qtkeychain
92+
qtlocation
93+
qtmultimedia
94+
qtpurchasing
95+
qtquickcontrols
96+
qtquickcontrols2
97+
qtscript
98+
qtscxml
99+
qtsensors
100+
qtserialbus
101+
qtserialport
102+
qtspeech
103+
qtsvg
104+
qttools
105+
qttranslations
106+
qtvirtualkeyboard
107+
qtwebchannel
108+
qtwebkit
109+
qtwebsockets
110+
qtwebview
111+
qtwinextras
112+
qtxmlpatterns
113+
qwt
114+
spatialite
115+
sqlite
116+
tiff
117+
xz
118+
zlib
119+
120+
When done, you can edit the build-mxe.sh script to set the path to your mxe installation.

ms-windows/mxe/build-mxe.sh

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/bin/bash
2+
###########################################################################
3+
# build-mxe.sh
4+
# ---------------------
5+
# Date : February 2018
6+
# Copyright : (C) 2018 by Alessandro Pasotti
7+
# Email : elpaso at itopen dot it
8+
###########################################################################
9+
# #
10+
# This program is free software; you can redistribute it and/or modify #
11+
# it under the terms of the GNU General Public License as published by #
12+
# the Free Software Foundation; either version 2 of the License, or #
13+
# (at your option) any later version. #
14+
# #
15+
###########################################################################
16+
17+
18+
set -e
19+
20+
# Usage: you can pass an optional "package" command to skip the build
21+
# and directly go to the packaging
22+
# This script needs to be called from the main QGIS directory, the
23+
# one which contains CMakeLists.txt
24+
25+
COMMAND=$1
26+
27+
# Location of current script
28+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
29+
PYDEPLOY=${DIR}/deploy.py
30+
31+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
32+
# Configuration: change this!
33+
34+
# Location of mxe install dir
35+
MXE=${HOME}/dev/mxe/
36+
37+
# Where the artifact will be saved
38+
39+
BUILD_DIR=`pwd`/build-mxe
40+
RELEASE_DIR=`pwd`/release-mxe
41+
42+
# End configuration
43+
44+
45+
46+
47+
if [[ "$COMMAND" != *"package"* ]]; then
48+
[ -d $BUILD_DIR ] && rm -rf $BUILD_DIR
49+
[ -d $RELEASE_DIR ] && rm -rf $RELEASE_DIR
50+
# Make sure dirs exist
51+
52+
[ -d $BUILD_DIR ] || mkdir $BUILD_DIR
53+
[ -d $RELEASE_DIR ] || mkdir $RELEASE_DIR
54+
55+
fi
56+
57+
pushd .
58+
59+
cd $BUILD_DIR
60+
61+
# Build
62+
63+
if [[ "$COMMAND" != *"package"* ]]; then
64+
65+
$MXE/usr/bin/i686-w64-mingw32.shared-cmake .. \
66+
-DCMAKE_BUILD_TYPE=Release \
67+
-DCMAKE_INSTALL_PREFIX=$RELEASE_DIR \
68+
-DENABLE_TESTS=OFF \
69+
-DWITH_QSPATIALITE=ON \
70+
-DWITH_APIDOC=OFF \
71+
-DWITH_QWTPOLAR=ON \
72+
-DWITH_ASTYLE=OFF \
73+
-DWITH_SERVER=OFF \
74+
-DWITH_BINDINGS=FALSE \
75+
-DQT_LRELEASE_EXECUTABLE=$MXE/usr/i686-w64-mingw32.shared/qt5/bin/lrelease \
76+
$ARGS
77+
78+
79+
make -j16 install
80+
81+
fi
82+
83+
# Collect deps
84+
85+
$PYDEPLOY --build=$RELEASE_DIR --objdump=$MXE/usr/bin/i686-w64-mingw32.shared-objdump ${RELEASE_DIR}/qgis.exe
86+
for dll in $(ls ${RELEASE_DIR}/*.dll); do \
87+
$PYDEPLOY --build=$RELEASE_DIR --objdump=$MXE/usr/bin/i686-w64-mingw32.shared-objdump $dll; \
88+
done
89+
90+
cp -r $MXE/usr/i686-w64-mingw32.shared/qt5/plugins $RELEASE_DIR/qt5
91+
92+
cat <<__TXT__ > ${RELEASE_DIR}/qt.conf
93+
[Paths]
94+
Plugins = ./qt5/plugins
95+
__TXT__
96+
97+
98+
popd
99+
100+
ZIP_NAME=release-`date +%Y-%m-%d-%H-%I-%S`.zip
101+
102+
zip -r $ZIP_NAME $RELEASE_DIR
103+
104+
echo "Release in $ZIP_NAME ready."

ms-windows/mxe/deploy.py

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#! /usr/bin/env python3
2+
"""pyWindeployqt
3+
4+
This is a wrapper for mingw32 objdump replacing windeployqt which is missing from MXE
5+
I don't know why they disabled it, but here it is.
6+
7+
Example:
8+
./deploy.py --build=~/ClionProjects/project/build/ \
9+
--objdump=/home/user/mxe/usr/bin/i686-w64-mingw32.shared-objdump \
10+
~/ClionProjects/project/build/project.exe;
11+
12+
"""
13+
14+
__author__ = 'Alexey Elymanov (strangeqargo@gmail.com)'
15+
16+
import subprocess
17+
import os
18+
import sys
19+
import re
20+
import os.path
21+
22+
import argparse
23+
parser = argparse.ArgumentParser()
24+
25+
parser.add_argument("--build", help="where to place libraries, optional, files will go to target location by default")
26+
parser.add_argument("--objdump", help="objdump executable (/home/user/mxe/usr/bin/i686-w64-mingw32.shared-objdump)")
27+
parser.add_argument("--libs", help="where to search for libraries (optional) infers from objdump")
28+
parser.add_argument("target")
29+
30+
args = parser.parse_args()
31+
if len(sys.argv) == 1 or not (args.libs or args.objdump):
32+
parser.print_help()
33+
sys.exit(1)
34+
35+
target = os.path.expanduser(args.target)
36+
objdump_path = os.path.expanduser(args.objdump)
37+
38+
if not args.build:
39+
build_path = os.path.expanduser(os.path.dirname(args.target)) + "/"
40+
else:
41+
build_path = os.path.expanduser(args.build)
42+
43+
libs = args.libs
44+
if not args.libs:
45+
libs = objdump_path.replace('/bin', '').replace('-objdump','')
46+
47+
48+
# build_path = "/home/user/ClionProjects/project/build/"
49+
# libs = "/home/user/mxe/usr/i686-w64-mingw32.shared"
50+
# objdump_path = "/home/user/mxe/usr/bin/i686-w64-mingw32.shared-objdump"
51+
# target = "project.exe"
52+
53+
54+
def run_check():
55+
return subprocess.getoutput("wine project.exe")
56+
57+
58+
def find_dll(dll):
59+
out = subprocess.getoutput("find " + libs + " | grep -i '" + dll+"$'")
60+
return out.strip('\n')
61+
62+
63+
def library_install_exe(out=''):
64+
out = run_check().splitlines()
65+
for line in out:
66+
# err = re.search('(err:module:import_dll (Library |Loading library)) (.*?\.dll) ', line)
67+
err = re.search('([^ ]+\.dll) \(which', line)
68+
if err is not None:
69+
70+
dll = err.group(1)
71+
dll = find_dll(dll)
72+
if dll is not None:
73+
copy_command = "cp " + dll + " " + build_path
74+
print("copy: ", copy_command)
75+
subprocess.getoutput(copy_command)
76+
library_install_exe(out)
77+
78+
79+
def library_install_objdump(path, level):
80+
if path in skip_libs or path in done:
81+
return
82+
83+
if level > 0:
84+
lib = find_dll(path)
85+
if lib == "": # not found
86+
skip_libs.append(path)
87+
print("Not found: " + path)
88+
return
89+
print(lib)
90+
subprocess.getoutput("cp " + lib + " " + build_path)
91+
92+
else:
93+
print("Processing target " + path)
94+
lib = path
95+
96+
done.append(path)
97+
98+
command = objdump_path + " -p " + lib + " | grep -o ': .*\.dll$'"
99+
res = subprocess.getstatusoutput(command)
100+
if (res[0] > 0):
101+
print("Error: objdump failed with " + lib)
102+
else:
103+
dlls = subprocess.getoutput(command).split("\n")
104+
for line in dlls:
105+
dll = (line.split(": "))[1]
106+
if dll not in done and dll not in skip_libs:
107+
level += 1
108+
library_install_objdump(dll, level)
109+
110+
skip_libs = list()
111+
done = list()
112+
113+
114+
def main():
115+
116+
os.chdir(build_path)
117+
118+
#library_install_exe(target)
119+
library_install_objdump(target, 0)
120+
121+
pass
122+
123+
main()

0 commit comments

Comments
 (0)