Commit 6c9e6854 authored by Philipp Hörist's avatar Philipp Hörist

Switch to using MSYS2 for Windows build

parent 94be050a
......@@ -19,6 +19,7 @@ stamp-h1
Makefile
__pycache__/
src/gtk/
win/_build_root
syntax: regexp
^config\.*
......
environment:
matrix:
- PYTHON: "C:\\Python34"
- MSYS: "C:\\msys64\\mingw32.exe"
branches:
only:
......@@ -10,49 +9,36 @@ branches:
clone_depth: 1
install:
- git clone --depth=1 --branch=gtk3 https://dev.gajim.org/gajim/gajim-plugins.git c:\projects\gajim-plugins
# Download & Install Dependencys
- ps: c:\\projects\\gajim\\dependencys.ps1
- set PATH=C:\\MinGW\\bin;%PATH%
- "%PYTHON%\\python.exe -m pip install --upgrade pip"
- "%PYTHON%\\python.exe -m pip install -r c:\\projects\\gajim\\requirements.txt"
# init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- ps: Add-Content C:\Python34\Lib\site-packages\google\__init__.py " "
- "%PYTHON%\\python.exe -m pip install --no-dependencies python-axolotl"
- "%PYTHON%\\python.exe -m pip install --global-option=build_ext --global-option --compiler=mingw32 python-axolotl-curve25519"
# Prepare Build Dir
- cd c:\\projects\\gajim\\
- xcopy . ..\gajim_built /e /i
- cd ..\gajim_built
# Copy Shipped Plugins
- xcopy ..\gajim-plugins\plugin_installer plugins\plugin_installer /e /i
# Compile Translation Strings
- cmd: for %%l in (po\*.po) do mkdir po\%%~nl & mkdir po\%%~nl\LC_MESSAGES & msgfmt -o po\%%~nl\LC_MESSAGES\gajim.mo %%l
install:
# Make Gajim.exe
- "%PYTHON%\\python.exe setup_win32.py build_exe"
- ps: |
function bash($command) {
Write-Host $command -NoNewline
cmd /c start /wait C:\msys64\usr\bin\sh.exe --login -c $command
Write-Host " - OK" -ForegroundColor Green
}
- move build\exe.win32-3.4 .
- rmdir build
- rename exe.win32-3.4 build
bash 'pacman -Sy --noconfirm git'
bash 'git clone https://dev.gajim.org/lovetox/gajim.git'
# Make Installer
- ps: '& "C:\Program Files (x86)\NSIS\makensis.exe" gajim.nsi'
- ps: '& "C:\Program Files (x86)\NSIS\makensis.exe" gajim-portable.nsi'
- cmd: '%MSYS% C:/msys64/home/appveyor/gajim/win/build.sh'
# Ugly workaround, because i found no way to tell when mingw32.exe returns
- cmd: timeout 900
# Push Installer Exe
- ps: $env:TIME_STRING=(get-date -UFormat "%Y-%m-%d").ToString()
- ps: Push-AppveyorArtifact Gajim.exe -FileName "Gajim-default-$($env:TIME_STRING).exe"
- ps: Push-AppveyorArtifact Gajim-Portable.exe -FileName "Gajim-portable-default-$($env:TIME_STRING).exe"
- ps: $env:BUILDROOT="C:\msys64\home\appveyor\gajim\win\_build_root"
- ps: Push-AppveyorArtifact "$($env:BUILDROOT)/Gajim.exe" -FileName "Gajim-Master-$($env:TIME_STRING).exe"
- ps: Push-AppveyorArtifact "$($env:BUILDROOT)/Gajim-Portable.exe" -FileName "Gajim-Portable-Master-$($env:TIME_STRING).exe"
build: off
# on_finish:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
deploy:
# FTP deployment provider settings
- provider: FTP
......
rmdir /S /Q ..\gajim_built
xcopy . ..\gajim_built /e /i
cd ..
cd gajim_built
xcopy ..\gajim-plugins\plugin_installer plugins\plugin_installer /e /i
rem copy C:\Python34\Lib\site-packages\gnome\msgfmt.exe gajim_built
rem copy C:\Windows\System32\msvcr100.dll gajim_built
for %%l in (po\*.po) do mkdir po\%%~nl & mkdir po\%%~nl\LC_MESSAGES & msgfmt -o po\%%~nl\LC_MESSAGES\gajim.mo %%l
"c:\python34\python.exe" setup_win32.py build_exe
move build\exe.win32-3.4 .
rmdir build
rename exe.win32-3.4 build
rem xcopy ..\win32com build\win32com /e /i
"C:\Program Files (x86)\NSIS\makensis" gajim.nsi
cd ..
pause
\ No newline at end of file
# Download the file to a specific location
$clnt = new-object System.Net.WebClient
$url = "https://gajim.org/downloads/snap/win/build/site-packages.zip"
$file = "c:\site-packages.zip"
$clnt.DownloadFile($url,$file)
# Unzip the file to specified location
$shell_app=new-object -com shell.application
$zip_file = $shell_app.namespace($file)
$destination = $shell_app.namespace("C:\Python34\Lib\site-packages")
$destination.Copyhere($zip_file.items())
cd src
python gajim.py
cd ..
# setup_win32.py (run me as python setup_win32.py py2exe -O2)
#
# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
# Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
#
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
#
import sys
import os
import site
from cx_Freeze import setup, Executable
SITEDIR = site.getsitepackages()[1]
INCLUDE_DLL_PATH = os.path.join(SITEDIR, "gnome")
sys.path.append('src')
# Collect the list of missing dll when cx_freeze builds the app
MISSING_DLL = ['libgtk-3-0.dll',
'libgdk-3-0.dll',
'libatk-1.0-0.dll',
'libgdk_pixbuf-2.0-0.dll',
'libjpeg-8.dll',
'libpango-1.0-0.dll',
'libpangocairo-1.0-0.dll',
'libpangoft2-1.0-0.dll',
'libpangowin32-1.0-0.dll',
'libgnutls-28.dll',
'libp11-kit-0.dll',
'libgstrtp-1.0-0.dll',
'libgstrtsp-1.0-0.dll',
'libgstrtspserver-1.0-0.dll',
'libfarstream-0.2-5.dll',
'libgstsdp-1.0-0.dll',
'libgsttag-1.0-0.dll',
'libgssdp-1.0-3.dll',
'libgstvideo-1.0-0.dll',
'libgstapp-1.0-0.dll',
'libgupnp-1.0-4.dll',
'libgstaudio-1.0-0.dll',
'libgupnp-igd-1.0-4.dll',
'libgstbase-1.0-0.dll',
'libnice-10.dll',
'librsvg-2-2.dll',
'libvisual-0.4-0.dll',
'libwebp-5.dll',
'libgstriff-1.0-0.dll',
'libepoxy-0.dll',
'libharfbuzz-0.dll',
'libtiff-5.dll',
'libjasper-1.dll',
'libgstpbutils-1.0-0.dll',
'liborc-0.4-0.dll',
'libgstnet-1.0-0.dll',
'libsoup-2.4-1.dll',
'liborc-test-0.4-0.dll',
'libavcodec-57.dll',
'libavutil-55.dll',
'libswresample-2.dll',
'libavformat-57.dll',
'libavfilter-6.dll',
'libgssapi-3.dll',
'libopenssl.dll',
'libsqlite3-0.dll',
'libproxy.dll',
'libstdc++.dll',
'libgstfft-1.0-0.dll']
# We need to add all the libraries too (for themes, etc..)
GTK_LIBS = {
'etc': ['dbus-1', 'fonts', 'gtk-3.0', 'pango'],
'lib': ['farstream-0.2', 'gdbus-2.0',
'gdk-pixbuf-2.0', 'gio', 'girepository-1.0',
'gstreamer-1.0', 'gtk-3.0'],
'share': ['dbus-1', 'farstream', 'fonts',
'glib-2.0',
'gst-plugins-base', 'gstreamer-1.0', 'gupnp-av',
'gupnp-dlna-2.0', 'icons', 'ssl', 'themes', 'xml']
}
# Create the list of includes as cx_freeze likes
INCLUDE_FILES = []
for dll in MISSING_DLL:
INCLUDE_FILES.append((os.path.join(INCLUDE_DLL_PATH, dll), dll))
# Let's add gtk libraries folders and files
for folder in GTK_LIBS:
for lib in GTK_LIBS[folder]:
folder_lib = os.path.join(folder, lib)
INCLUDE_FILES.append((os.path.join(INCLUDE_DLL_PATH, folder_lib),
folder_lib))
#Let's add gtk locales that we support in Gajim
for language in next(os.walk('po'))[1]:
target_dir = os.path.join('share', 'locale', language)
language_dir = os.path.join(INCLUDE_DLL_PATH, target_dir)
if os.path.isdir(language_dir):
INCLUDE_FILES.append((language_dir, target_dir))
OPTIONS = {
'build_exe': {
'includes': ['gi', 'numbers', 'win32com.client', 'win32com.server'],
'packages': ['gi', 'cffi', 'cryptography', 'google', 'axolotl',
'pkg_resources', 'Crypto', 'pycparser', 'keyring',
'PIL', 'idna', 'qrcode', 'certifi'],
'include_files': INCLUDE_FILES,
}
}
setup(
name='Gajim',
version='0.16.10',
description='A full featured Jabber client',
author='Gajim Development Team',
url='http://gajim.org/',
download_url='http://gajim.org/downloads.php',
license='GPL',
options=OPTIONS,
executables=[Executable('src/gajim.py', icon='data/pixmaps/gajim.ico',
base='Win32GUI')],
)
# Windows Installer
We use [msys2](http://www.msys2.org/) for creating the Windows installer
and development on Windows.
### Development
-----------
Download [msys2](http://www.msys2.org/) (msys2-x86_64-xxx.exe) and follow the install instructions on the [msys2](http://www.msys2.org/) startpage (**Important!**)
* Fork the master branch on dev.gajim.org
* Execute ``C:\msys64\mingw32.exe``
* Run ``pacman -S git`` to install git
* Run ``git clone https://dev.gajim.org/USERNAME/gajim.git``
* Run ``cd gajim/win`` to end up where this README exists.
* Execute ``./dev_env.sh`` to install all the needed dependencies.
* Now go to the git root dir ``cd ..``
* Launch Gajim ``./launch.sh``
### Build Gajim / Creating an Installer
---------------------
Follow the steps in the Development section, but instead of ``./dev_env.sh`` execute ``./build.sh``.
You can supply a git tag ``./build.sh [git-tag]``.
Or dont supply it, then current HEAD is build.
Both the installer and the portable installer should appear in ``C:\msys64\home\USER\gajim\win\_build_root``.
This diff is collapsed.
#!/usr/bin/env bash
# Copyright 2016 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
DIR="$( cd "$( dirname "$0" )" && pwd )"
source "$DIR"/_base.sh
function main {
local GIT_TAG=${1:-"master"}
[[ -d "${BUILD_ROOT}" ]] && (echo "${BUILD_ROOT} already exists"; exit 1)
# started from the wrong env -> switch
if [ $(echo "$MSYSTEM" | tr '[A-Z]' '[a-z]') != "$MINGW" ]; then
"/${MINGW}.exe" "$0"
exit $?
fi
install_pre_deps
create_root
install_deps
install_gajim "$GIT_TAG"
cleanup_install
build_installer
}
main "$@";
#!/usr/bin/env bash
set -e
function main {
pacman --noconfirm -S --needed \
git \
mingw-w64-i686-toolchain \
mingw-w64-i686-gdk-pixbuf2 \
mingw-w64-i686-gtk3 \
mingw-w64-i686-gstreamer \
intltool \
mingw-w64-i686-sqlite3 \
mingw-w64-i686-python3 \
mingw-w64-i686-python3-gobject \
mingw-w64-i686-python3-pip
pip3 install setuptools_scm
PIP_REQUIREMENTS="\
pyasn1
certifi
git+https://dev.gajim.org/gajim/python-nbxmpp.git
protobuf
git+https://github.com/dlitz/pycrypto.git
cryptography
pyopenssl
python-gnupg
docutils
qrcode
keyring
"
pip3 install --no-binary ":all:" \
--force-reinstall $(echo "$PIP_REQUIREMENTS" | tr ["\\n"] [" "])
pip3 install python-axolotl
}
main;
[Settings]
gtk-theme-name=VimixLight
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2016 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
"""Creates simple Python .exe launchers for gui and cli apps
./create-launcher.py "3.8.0" <target-dir>
"""
import os
import sys
import subprocess
import shlex
import tempfile
import shutil
import struct
from distutils.spawn import find_executable
def build_resource(rc_path, out_path):
"""Raises subprocess.CalledProcessError"""
def is_64bit():
return struct.calcsize("P") == 8
subprocess.check_call(
["windres", "-O", "coff", "-F",
"pe-x86-64" if is_64bit() else "pe-i386", rc_path,
"-o", out_path])
def get_build_args():
python_name = os.path.splitext(os.path.basename(sys.executable))[0]
python_config = os.path.join(
os.path.dirname(sys.executable), python_name + "-config")
cflags = subprocess.check_output(
["sh", python_config, "--cflags"]).strip()
libs = subprocess.check_output(
["sh", python_config, "--libs"]).strip()
cflags = os.fsdecode(cflags)
libs = os.fsdecode(libs)
return shlex.split(cflags) + shlex.split(libs)
def build_exe(source_path, resource_path, is_gui, out_path):
args = ["gcc", "-s"]
if is_gui:
args.append("-mwindows")
args.extend(["-o", out_path, source_path, resource_path])
args.extend(get_build_args())
subprocess.check_call(args)
def get_launcher_code(entry_point):
template = """\
#include "Python.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
int result;
LPWSTR *szArglist;
int nArgs;
int i;
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if( NULL == szArglist )
{
printf("CommandLineToArgvW failed");
return 0;
}
Py_NoUserSiteDirectory = 1;
Py_IgnoreEnvironmentFlag = 1;
Py_DontWriteBytecodeFlag = 1;
Py_FrozenFlag = 1;
Py_Initialize();
PySys_SetArgvEx(__argc, szArglist, 0);
FILE* file = fopen("../gajim/src/%(filename)s", "r");
PyRun_SimpleString("import sys; import os;"
"os.chdir('../gajim/src');"
"sys.path.append(os.getcwd());"
"sys.frozen=True;"
);
result = PyRun_SimpleFile(file, "../gajim/src/%(filename)s");
Py_Finalize();
return result;
}
"""
return template % {"filename": entry_point}
def get_resouce_code(filename, file_version, file_desc, icon_path,
product_name, product_version, company_name):
template = """\
1 ICON "%(icon_path)s"
1 VERSIONINFO
FILEVERSION %(file_version_list)s
PRODUCTVERSION %(product_version_list)s
FILEOS 0x4
FILETYPE 0x1
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "%(company_name)s"
VALUE "FileDescription", "%(file_desc)s"
VALUE "FileVersion", "%(file_version)s"
VALUE "InternalName", "%(internal_name)s"
VALUE "OriginalFilename", "%(filename)s"
VALUE "ProductName", "%(product_name)s"
VALUE "ProductVersion", "%(product_version)s"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
"""
def to_ver_list(v):
return ",".join(map(str, (list(map(int, v.split("."))) + [0] * 4)[:4]))
file_version_list = to_ver_list(file_version)
product_version_list = to_ver_list(product_version)
return template % {
"icon_path": icon_path, "file_version_list": file_version_list,
"product_version_list": product_version_list,
"file_version": file_version, "product_version": product_version,
"company_name": company_name, "filename": filename,
"internal_name": os.path.splitext(filename)[0],
"product_name": product_name, "file_desc": file_desc,
}
def build_launcher(out_path, icon_path, file_desc, product_name, product_version,
company_name, entry_point, is_gui):
src_ico = os.path.abspath(icon_path)
target = os.path.abspath(out_path)
file_version = product_version
dir_ = os.getcwd()
temp = tempfile.mkdtemp()
try:
os.chdir(temp)
with open("launcher.c", "w") as h:
h.write(get_launcher_code(entry_point))
shutil.copyfile(src_ico, "launcher.ico")
with open("launcher.rc", "w") as h:
h.write(get_resouce_code(
os.path.basename(target), file_version, file_desc,
"launcher.ico", product_name, product_version, company_name))
build_resource("launcher.rc", "launcher.res")
build_exe("launcher.c", "launcher.res", is_gui, target)
finally:
os.chdir(dir_)
shutil.rmtree(temp)
def main():
argv = sys.argv
version = argv[1]
target = argv[2]
company_name = "Gajim"
misc = os.path.dirname(os.path.realpath(__file__))
build_launcher(
os.path.join(target, "Gajim.exe"),
os.path.join(misc, "gajim.ico"), "Gajim", "Gajim",
version, company_name, 'gajim.py', True)
build_launcher(
os.path.join(target, "Gajim-Debug.exe"),
os.path.join(misc, "gajim.ico"), "Gajim", "Gajim",
version, company_name, 'gajim.py', False)
build_launcher(
os.path.join(target, "history_manager.exe"),
os.path.join(misc, "gajim.ico"), "History Manager", "History Manager",
version, company_name, 'history_manager.py', True)
if __name__ == "__main__":
main()
# -*- coding: utf-8 -*-
# Copyright 2016 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
"""
Deletes unneeded DLLs and checks DLL dependencies.
Execute with the build python, will figure out the rest.
"""
import subprocess
import os
import sys
import gi
gi.require_version("GIRepository", "2.0")
from gi.repository import GIRepository
def get_required_by_typelibs():
deps = set()
repo = GIRepository.Repository()
for tl in os.listdir(repo.get_search_path()[0]):
namespace, version = os.path.splitext(tl)[0].split("-", 1)
repo.require(namespace, version, 0)
lib = repo.get_shared_library(namespace)
if lib:
deps.update(lib.split(","))
return deps
EXTENSIONS = [".exe", ".pyd", ".dll"]
SYSTEM_LIBS = ['advapi32.dll',
"cabinet.dll", "comctl32.dll", "comdlg32.dll", "crypt32.dll", "d3d9.dll",
"dnsapi.dll", "dsound.dll", "dwmapi.dll", "gdi32.dll", "imm32.dll",
"iphlpapi.dll", "kernel32.dll", "ksuser.dll", "msi.dll", "msimg32.dll",
"msvcr71.dll", "msvcr80.dll", "msvcrt.dll", "ole32.dll", "oleaut32.dll",
"opengl32.dll", "rpcrt4.dll", "setupapi.dll", "shell32.dll", "user32.dll",
"usp10.dll", "winmm.dll", "winspool.drv", "wldap32.dll", "ws2_32.dll",
"wsock32.dll", "shlwapi.dll"
]
def get_dependencies(filename):
deps = []