Skip to content

Commit

Permalink
mumble, murmur: final adjustments for the win32-static buildenv.
Browse files Browse the repository at this point in the history
With this change, CONFIG(static) on Windows will cause the Mumble client's
application logic to be built into a .DLL called mumble_app.dll
(based on pcgod's previous DLL changeset).

Since src/mumble will now be built as a DLL, a wrapper executable is available
in src/mumble_exe. This wrapper is currently implemented such that it will
load mumble_app.dll from the directory that it resides in.

This means that when building statically, src/mumble and src/mumble_exe will
now give us the following products:

  src/mumble:      mumble_app.dll
  src/mumble_exe:  mumble.exe

Along with the two major points above, this change also adds a Python script
to the build, 'gen-mumble_app-qt-def.py', whose job is to construct a module
definition (.def) file for mumble_app.dll. The generated module definition
lists the Qt symbols that are needed for the manual positioning plugin to work.

If we need to expose more symbols in the future (say we want to implement
more plugin kinds than the current positional audio plugins), we now have
the infrastructure in place to do that.
  • Loading branch information
mkrautz committed Aug 25, 2013
1 parent 7c2d1a3 commit 6da2930
Show file tree
Hide file tree
Showing 13 changed files with 510 additions and 22 deletions.
4 changes: 4 additions & 0 deletions main.pro
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ CONFIG *= ordered debug_and_release

SUBDIRS *= src/mumble

win32:CONFIG(static) {
SUBDIRS *= src/mumble_exe
}

!CONFIG(no-plugins) {
SUBDIRS *= plugins
}
Expand Down
7 changes: 5 additions & 2 deletions plugins/manual/features/qt_dynamic_lookup.prf
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
LIBS -= -lQtCore -lQtGui
LIBS -= -lQtCored -lQtGuid
LIBS -= -lQt5Core -lQt5Gui -lQt5Widgets
LIBS -= -lQt5Cored -lQt5Guid -lQt5Widgetsd

macx {
LIBS += -undefined dynamic_lookup
LIBS -= -lQtCore -lQtGui
LIBS -= -lQt5Core -lQt5Gui -lQt5Widgets
}
10 changes: 10 additions & 0 deletions plugins/manual/manual.pro
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,13 @@ isEqual(QT_MAJOR_VERSION, 5) {
HEADERS = manual.h
SOURCES = manual.cpp
FORMS += manual.ui

CONFIG(debug, debug|release) {
LIBPATH *= ../../debug
}

CONFIG(release, debug|release) {
LIBPATH *= ../../release
}

LIBS *= -lmumble_app
8 changes: 0 additions & 8 deletions plugins/plugins.pro
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,4 @@ DIST = plugins.pri

win32 {
SUBDIRS += aoc arma2 bf1942 bf2 bf3 bf2142 bfbc2 bfheroes blacklight borderlands borderlands2 breach cod2 cod4 cod5 codmw2 codmw2so cs css dods dys etqw tf2 gmod gtaiv gw hl2dm insurgency jc2 l4d l4d2 lol lotro sr sto ut2004 ut3 ut99 wolfet wow

# Temporarily disable the manual plugin
# for static builds on Windows. We'll
# have to figure out a smart way of allowing
# the manual plugin to access Qt symbols.
CONFIG(static) {
SUBDIRS -= manual
}
}
145 changes: 145 additions & 0 deletions scripts/gen-mumble_app-qt-def.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/usr/bin/env python
#
# Copyright (C) 2013 Mikkel Krautz <mikkel@krautz.dk>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the Mumble Developers nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# gen-mumble_app-qt-def.py creates a module definition file (.def)
# for the Qt symbols that mumble_app.dll needs to export to support
# the manual.dll plugin.
#
# The .def file is generated by running dumpbin.exe on a set of static
# Qt libraries, filtering the output to only include the symbols that
# we're interested in.
#
# The filtering process is simply a substring match on the list of
# MSVC mangled names. It might make sense to tune the filter in the
# future, since the current iteration is likely to produce unneeded
# exports.

import subprocess
import sys
import re
import os

# qtSymbols list the Qt symbols that we're interested in exporting.
qtSymbols = [
# QtCore
'QObject',
'QCoreApplication',
'QString',
'QBasicAtomicInt',

# QtGui/QtWidgets
'QGroupBox',
'QGridLayout',
'QGraphicsScene',
'QWidget',
'QDialog',
'QDialogButton',
'QLabel',
'QLineEdit',
'QAbstractSlider',
'QBrush',
'QGraphicsView',
'QPushButton',
'QDial',
'QSpinBox',
'QValidator',
'QSpacerItem',
'QLayoutItem',
'QAbstractScrollArea',
'QVBoxLayout',
'QLayout',
'QAbstractSpinBox',
'QFrame',
'QBoxLayout',
'QDoubleSpinBox',
'QObject',
'QMetaObject',
'QAbstractButton',
'QPen',
'QHBoxLayout',
'QGraphicsItem',
'QColor',
'QGraphicsView',
'QSizePolicy',
'QMouseEvent',
'QRectF',
'QPointF',
]

def processExports(f, libs, symbols):
'''
processExports writes a module definition file (.def) to the file object
`f' for all symbols found in the static libraries given in `libs' that
match any of the strings found in `symbols'.
'''
p = subprocess.Popen(['dumpbin.exe', '/linkermember'] + libs, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
raise Exception('dumpbin.exe failed: %s', stderr)

symbol_re = re.compile('^.*\ (.*(%s)+?.*)$' % '|'.join(symbols))
f.write('EXPORTS\n\n')

for line in stdout.split('\r\n'):
m = symbol_re.match(line)
if m is not None:
mangled, matchedsym = m.groups()
f.write(mangled + '\r\n')

def main():
if len(sys.argv) < 4:
print 'Usage: gen-mumble_app-qt-def.py <release|debug> <qt-lib-path> <outfn>'
sys.exit(1)

kind = sys.argv[1]
qtLibDir = sys.argv[2]
outFn = sys.argv[3]

# Find the absolute path of the Qt libs we're interested in.
#
# If we're in debug mode, look for libraries with a 'd' suffix,
# such as 'QtGuid', rather than 'QtGui'.
#
# Non-existant libs are skipped. This is to allow the script to
# work on both Qt 4 and 5.
suffix = ''
if kind == 'debug':
suffix = 'd'
libs = ['QtCore', 'QtGui', 'QtWidgets']
libs = ['%s%s.lib' % (lib, suffix) for lib in libs]
abslibs = [os.path.join(qtLibDir, lib) for lib in libs]
abslibs = [lib for lib in abslibs if os.path.exists(lib)]

with open(outFn, 'w') as f:
processExports(f, abslibs, qtSymbols)

if __name__ == '__main__':
main()
26 changes: 24 additions & 2 deletions src/mumble/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@
#include "CrashReporter.h"
#include "SocketRPC.h"

#if defined(USE_STATIC) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#if defined(USE_STATIC_QT_PLUGINS) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
Q_IMPORT_PLUGIN(qico)
Q_IMPORT_PLUGIN(qsvg)
Q_IMPORT_PLUGIN(qsvgicon)
# ifdef Q_OS_MAC
Q_IMPORT_PLUGIN(qicnsicon)
# endif
#endif // USE_STATIC
#endif

#ifdef BOOST_NO_EXCEPTIONS
namespace boost {
Expand Down Expand Up @@ -166,7 +166,11 @@ bool QAppMumble::winEventFilter(MSG *msg, long *result) {
# endif
#endif

#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG)
extern "C" _declspec(dllexport) int main(int argc, char **argv) {
#else
int main(int argc, char **argv) {
#endif
int res = 0;

QT_REQUIRE_VERSION(argc, argv, "4.4.0");
Expand Down Expand Up @@ -574,3 +578,21 @@ int main(int argc, char **argv) {
#endif
return res;
}

#if defined(Q_OS_WIN) && defined(QT_NO_DEBUG)
extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);

extern "C" _declspec(dllexport) int MumbleMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdArg, int cmdShow) {
Q_UNUSED(cmdArg);

QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit();
int argc = 0;

// qWinMain takes argv as a reference.
QVector<char *> argv;
qWinMain(instance, prevInstance, cmdParam.data(), cmdShow, argc, argv);

int result = main(argc, argv.data());
return result;
}
#endif
60 changes: 51 additions & 9 deletions src/mumble/mumble.pro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@ include(../mumble.pri)

DEFINES *= MUMBLE
TEMPLATE = app
TARGET = mumble

CONFIG(static) {
# On Windows, building a static client
# means building the main app into a DLL.
win32 {
TEMPLATE = lib
TARGET = mumble_app
VERSION =

CONFIG -= static
CONFIG += shared qt_static mumble_dll
DEFINES += USE_MUMBLE_DLL QT_SHARED

DEF_FILE = $${DESTDIR}/$${TARGET}.def

QMAKE_LFLAGS += /DEF:$${DEF_FILE}
QMAKE_LFLAGS += /ignore:4102 # export of deleting destructor
QMAKE_LFLAGS += /ignore:4197 # specified multiple times

CONFIG(debug, debug|release) {
DEF_KIND = debug
}

CONFIG(release, debug|release) {
DEF_KIND = release
}

gendef.commands = python ../../scripts/gen-mumble_app-qt-def.py $${DEF_KIND} $$[QT_INSTALL_LIBS] $${DEF_FILE}
QMAKE_EXTRA_TARGETS *= gendef
PRE_TARGETDEPS *= gendef
QMAKE_DISTCLEAN *= $${DEF_FILE}
}

DEFINES *= USE_STATIC
CONFIG += static_qt_plugins
}

QT *= network sql xml svg
isEqual(QT_MAJOR_VERSION, 5) {
QT *= widgets
Expand All @@ -16,7 +54,6 @@ isEqual(QT_MAJOR_VERSION, 5) {
CONFIG += no-cocoa
}

TARGET = mumble
HEADERS *= BanEditor.h ACLEditor.h ConfigWidget.h Log.h AudioConfigDialog.h AudioStats.h AudioInput.h AudioOutput.h AudioOutputSample.h AudioOutputSpeech.h AudioOutputUser.h CELTCodec.h CustomElements.h MainWindow.h ServerHandler.h About.h ConnectDialog.h GlobalShortcut.h TextToSpeech.h Settings.h Database.h VersionCheck.h Global.h UserModel.h Audio.h ConfigDialog.h Plugins.h PTTButtonWidget.h LookConfig.h Overlay.h OverlayText.h SharedMemory.h AudioWizard.h ViewCert.h TextMessage.h NetworkConfig.h LCD.h Usage.h Cert.h ClientUser.h UserEdit.h Tokens.h UserView.h RichTextEditor.h UserInformation.h SocketRPC.h VoiceRecorder.h VoiceRecorderDialog.h WebFetch.h ../SignalCurry.h
SOURCES *= BanEditor.cpp ACLEditor.cpp ConfigWidget.cpp Log.cpp AudioConfigDialog.cpp AudioStats.cpp AudioInput.cpp AudioOutput.cpp AudioOutputSample.cpp AudioOutputSpeech.cpp AudioOutputUser.cpp main.cpp CELTCodec.cpp CustomElements.cpp MainWindow.cpp ServerHandler.cpp About.cpp ConnectDialog.cpp Settings.cpp Database.cpp VersionCheck.cpp Global.cpp UserModel.cpp Audio.cpp ConfigDialog.cpp Plugins.cpp PTTButtonWidget.cpp LookConfig.cpp OverlayClient.cpp OverlayConfig.cpp OverlayEditor.cpp OverlayEditorScene.cpp OverlayUser.cpp OverlayUserGroup.cpp Overlay.cpp OverlayText.cpp SharedMemory.cpp AudioWizard.cpp ViewCert.cpp Messages.cpp TextMessage.cpp GlobalShortcut.cpp NetworkConfig.cpp LCD.cpp Usage.cpp Cert.cpp ClientUser.cpp UserEdit.cpp Tokens.cpp UserView.cpp RichTextEditor.cpp UserInformation.cpp SocketRPC.cpp VoiceRecorder.cpp VoiceRecorderDialog.cpp WebFetch.cpp
SOURCES *= smallft.cpp
Expand Down Expand Up @@ -127,7 +164,11 @@ unix:!CONFIG(bundled-opus):system(pkg-config --exists opus) {
}

win32 {
RC_FILE = mumble.rc
CONFIG(mumble_dll) {
RC_FILE = mumble_dll.rc
} else {
RC_FILE = mumble.rc
}
HEADERS *= GlobalShortcut_win.h TaskList.h
SOURCES *= GlobalShortcut_win.cpp TextToSpeech_win.cpp Overlay_win.cpp SharedMemory_win.cpp Log_win.cpp os_win.cpp TaskList.cpp ../../overlay/HardHook.cpp ../../overlay/ods.cpp
LIBS *= -l"$$(DXSDK_DIR)Lib/x86/dxguid" -l"$$(DXSDK_DIR)Lib/x86/dinput8" -lsapi -lole32 -lws2_32 -ladvapi32 -lwintrust -ldbghelp -llibsndfile-1 -lshell32 -lshlwapi -luser32 -lgdi32
Expand All @@ -144,12 +185,14 @@ win32 {
CONFIG *= wasapi
}

!CONFIG(no-elevation) {
CONFIG(release, debug|release) {
QMAKE_LFLAGS *= /MANIFESTUAC:\"level=\'asInvoker\' uiAccess=\'true\'\"
!CONFIG(mumble_dll) {
!CONFIG(no-elevation) {
CONFIG(release, debug|release) {
QMAKE_LFLAGS *= /MANIFESTUAC:\"level=\'asInvoker\' uiAccess=\'true\'\"
}
}
QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\n\\t)$$quote(mt.exe -nologo -updateresource:$(DESTDIR_TARGET);1 -manifest mumble.appcompat.manifest)
}
QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\n\\t)$$quote(mt.exe -nologo -updateresource:$(DESTDIR_TARGET);1 -manifest mumble.appcompat.manifest)
}

unix {
Expand Down Expand Up @@ -367,9 +410,8 @@ CONFIG(no-update) {
RESOURCES *= mumble_tango.qrc
}

CONFIG(static) {
DEFINES *= USE_STATIC

CONFIG(static_qt_plugins) {
DEFINES += USE_STATIC_QT_PLUGINS
QTPLUGIN += qtaccessiblewidgets qico qsvg qsvgicon
macx {
QTPLUGIN += qicnsicon
Expand Down
46 changes: 46 additions & 0 deletions src/mumble/mumble_dll.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <winver.h>

IDI_ICON1 ICON DISCARDABLE "..\\..\\icons\\mumble.ico"

#ifndef DEBUG
#define VER_DEBUG 0L
#else
#define VER_DEBUG VS_FF_DEBUG
#endif

#ifdef SNAPSHOT_BUILD
#define VER_RELEASE VS_FF_SPECIALBUILD|VS_FF_PRERELEASE
#else
#define VER_RELEASE 0L
#endif

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,5,0
PRODUCTVERSION 1,2,5,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS (VER_DEBUG|VER_RELEASE)
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "Thorvald Natvig"
VALUE "FileDescription", "Mumble - Low-latency VoIP client"
VALUE "FileVersion", "1.2.5"
VALUE "ProductVersion", "1.2.5"
VALUE "LegalCopyright", "Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>"
VALUE "OriginalFilename", "mumble_app.dll"
VALUE "ProductName", "Mumble"
#ifdef SNAPSHOT_BUILD
VALUE "SpecialBuild", "Snapshot development release"
#endif
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
Loading

0 comments on commit 6da2930

Please sign in to comment.