Skip to content

Commit

Permalink
Compile NVDA with Visual Studio 2017. (#7568)
Browse files Browse the repository at this point in the history
    * Switch to using SCons 3.0 from a git mirror we manage.
    * Compile NVDA with the Windows 10 SDK, replace GetVersion with versionHelper macros, and remove a pre-vista TSF check.
                       * Instruct appveyor to use its Visual Studio 2017 image
* Update readme to mention Visual Studio 2017
* iSimpleDOMNode_sconscript:  don't lose existing flags when adding c_ext and /I to MIDLFLAGS as this was dropping /x64 which is needed for compiling when 64 bit.
* nvdaHelper sconscripts: now we are always using the Windows 10 SDK, we can compile nvdaHelperLocalWin10 using the same infrastructure as nvdaHelperRemote and nvdaHelperLocal etc, except that rather than /mt, /ZW should be used. This removes a great deal of code from the nvdaHelperLocalWin10 sconscript.
* Readme.md: update VS 2017 section with extra needed dependency
* Clarify error message when VC++ 14.1 is missing.
* Ensure that all Python directories exist, eitherwise raise an error alerting the user to the fact they may need to run git submodule update --init
* nvdaHelperLocalWin10 sconscript:  search versioned directories from newest to oldest to find the vc restributables.
  • Loading branch information
michaelDCurran committed Oct 18, 2017
1 parent 2221bab commit 58e1946
Show file tree
Hide file tree
Showing 18 changed files with 88 additions and 175 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -18,3 +18,6 @@
path = include/pyserial
url = https://github.com/pyserial/pyserial.git
ignore = untracked
[submodule "include/scons"]
path = include/scons
url = https://github.com/nvaccess/scons
1 change: 1 addition & 0 deletions appveyor.yml
@@ -1,3 +1,4 @@
os: Visual Studio 2017
version: "{branch}-{build}"

branches:
Expand Down
1 change: 1 addition & 0 deletions include/scons
Submodule scons added at cad5e5
2 changes: 1 addition & 1 deletion nvdaHelper/ISimpleDOM_sconscript
Expand Up @@ -31,7 +31,7 @@ idlFile=env.Substfile(

tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
source=idlFile,
MIDLFLAGS=['/c_ext','/I',Dir('.')],
MIDLFLAGS=[env['MIDLFLAGS'],'/c_ext','/I',Dir('.')],
)
# #7036: hack: Ignore midl.exe when deciding to rebuild, as its position in the dependencies
# is different in the run before the idl files are copied versus subsequent runs.
Expand Down
41 changes: 32 additions & 9 deletions nvdaHelper/archBuild_sconscript
Expand Up @@ -73,9 +73,9 @@ def COMProxyDllBuilder(env,target,source,proxyClsid):
return proxyDll
env.AddMethod(COMProxyDllBuilder,'COMProxyDll')

# We only support compiling with MSVC 14 (2015)
if not env.get('MSVC_VERSION','').startswith('14.'):
raise RuntimeError("Microsoft Visual C++ 14 not found")
# We only support compiling with MSVC 14.1 (2017)
if not env.get('MSVC_VERSION')=='14.1':
raise RuntimeError("Visual C++ 14.1 (Visual Studio 2017) not found")


TARGET_ARCH=env['TARGET_ARCH']
Expand All @@ -84,7 +84,14 @@ release=env['release']
signExec=env['signExec'] if env['certFile'] else None

#Some defines and includes for the environment
env.Append(CPPDEFINES=['UNICODE','_CRT_SECURE_NO_DEPRECATE',('LOGLEVEL','${nvdaHelperLogLevel}'),('_WIN32_WINNT','_WIN32_WINNT_WS03')])
env.Append(
CPPDEFINES=[
'UNICODE',
'_CRT_SECURE_NO_DEPRECATE',
('LOGLEVEL','${nvdaHelperLogLevel}'),
('_WIN32_WINNT','_WIN32_WINNT_WIN7')
]
)
env.Append(CCFLAGS=['/W3','/WX'])
if 'analyze' in debug:
env.Append(CCFLAGS=['/analyze'])
Expand All @@ -98,7 +105,13 @@ if 'analyze' in debug:
env.Append(CXXFLAGS=['/EHsc'])

env.Append(CPPPATH=['#/include','#/miscDeps/include',Dir('.').abspath])
env.Append(LINKFLAGS=['/incremental:no','/WX'])
env.Append(
LINKFLAGS=[
'/incremental:no',
'/WX',
'/subsystem:windows,6.01',
]
)
env.Append(LINKFLAGS='/release') #We always want a checksum in the header
env.Append(MIDLFLAGS='/x64' if TARGET_ARCH=='x86_64' else '/win32')

Expand All @@ -109,10 +122,7 @@ else:
env.Append(CCFLAGS='/GL')
env.Append(LINKFLAGS=['/LTCG'])

if 'debugCRT' in debug:
env.Append(CCFLAGS=['/MTd'])
else:
env.Append(CCFLAGS=['/MT'])
if 'debugCRT' not in debug:
env.Append(CPPDEFINES=['NDEBUG'])

if 'RTC' in debug:
Expand All @@ -123,6 +133,15 @@ if 'RTC' in debug:
env.Append(PDB='${TARGET}.pdb')
env.Append(LINKFLAGS='/OPT:REF') #having symbols usually turns this off but we have no need for unused symbols

win10env=env.Clone()
win10env.Append(CXXFLAGS='/ZW')
Export('win10env')

if 'debugCRT' in debug:
env.Append(CCFLAGS=['/MTd'])
else:
env.Append(CCFLAGS=['/MT'])

Export('env')

acrobatAccessRPCStubs=env.SConscript('acrobatAccess_sconscript')
Expand Down Expand Up @@ -155,6 +174,10 @@ if TARGET_ARCH=='x86':
if signExec:
env.AddPostAction(localLib[0],[signExec])
env.Install(libInstallDir,localLib)
win10localLib=env.SConscript('localWin10/sconscript',)
if signExec:
env.AddPostAction(win10localLib[0],[signExec])
env.Install(libInstallDir,win10localLib)

clientLib=env.SConscript('client/sconscript')
Export('clientLib')
Expand Down
4 changes: 2 additions & 2 deletions nvdaHelper/espeak/sconscript
Expand Up @@ -77,11 +77,11 @@ def espeak_compileDict_buildAction(target,source,env):
lang=source[0].name.split('_')[0]
v=espeak_VOICE(languages=lang+'\x00')
if espeak.espeak_SetVoiceByProperties(ctypes.byref(v))!=0:
print "espeak_compileDict_action: failed to switch to language %s"%lang
print("espeak_compileDict_action: failed to switch to language %s"%lang)
return 1
dictPath=os.path.split(source[0].abspath)[0]+'/'
if espeak.espeak_ng_CompileDictionary(dictPath,None,0,None)!=0:
print "espeak_compileDict_action: failed to compile dictionary for language %s"%lang
print("espeak_compileDict_action: failed to compile dictionary for language %s"%lang)
return
finally:
espeak.espeak_Terminate()
Expand Down
4 changes: 0 additions & 4 deletions nvdaHelper/local/mixer.cpp
Expand Up @@ -11,10 +11,6 @@ Copyright 2008-2014 NV Access Limited.
This license can be found at:
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
// This file can only compile for Vista and above
// NVDA will not call this function on lower Loperating Systems
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600

#include <comdef.h>
#include <comip.h>
Expand Down
56 changes: 19 additions & 37 deletions nvdaHelper/localWin10/sconscript
Expand Up @@ -13,48 +13,21 @@
###

import os
import glob

Import(
'env',
'win10env',
'sourceDir',
'libInstallDir',
'localLib',
)

TARGET_ARCH=env['TARGET_ARCH']
debug=env['nvdaHelperDebugFlags']
release=env['release']
signExec=env['signExec'] if env['certFile'] else None
env=win10env.Clone()

progFilesX86 = os.getenv("ProgramFiles(x86)")
if not progFilesX86:
# 32 bit system, so only one Program Files directory.
progFilesX86 = os.getenv("ProgramFiles")

env.Append(CPPDEFINES=[
'UNICODE', '_CRT_SECURE_NO_DEPRECATE',
('LOGLEVEL','${nvdaHelperLogLevel}')])
env.Append(CCFLAGS=['/W3', '/WX'])
env.Append(CXXFLAGS=['/EHsc', '/ZW',
r'/AI%s\Microsoft Visual Studio 14.0\VC\vcpackages' % progFilesX86,
r'/AI%s\Windows Kits\10\UnionMetadata' % progFilesX86])
env.Append(CPPPATH=[Dir('..').abspath])
env.Append(LINKFLAGS=['/incremental:no', '/WX'])
env.Append(LINKFLAGS='/release') # We always want a checksum in the header

if not release:
env.Append(CCFLAGS=['/Od'])
else:
env.Append(CCFLAGS='/O2')
env.Append(CCFLAGS='/GL')
env.Append(LINKFLAGS=['/LTCG'])

if 'RTC' in debug:
env.Append(CCFLAGS=['/RTCsu'])

# We always want debug symbols
env.Append(PDB='${TARGET}.pdb')
env.Append(LINKFLAGS='/OPT:REF') #having symbols usually turns this off but we have no need for unused symbols

localWin10Lib = env.SharedLibrary(
target="nvdaHelperLocalWin10",
source=[
Expand All @@ -65,14 +38,23 @@ localWin10Lib = env.SharedLibrary(
],
LIBS=["oleaut32", localLib[2]],
)
if signExec:
env.AddPostAction(localWin10Lib[0], [signExec])
env.Install(libInstallDir, localWin10Lib)

# UWP dlls can only be dynamically linked with the CRT,
# but some systems might not have this version of the CRT.
# Therefore, we must include it.
vcRedist = os.path.join(progFilesX86, r"Microsoft Visual Studio 14.0\VC\redist\onecore\x86\Microsoft.VC140.CRT")
# VS 2017 keeps changing the path to reflect the latest major.minor.build version which we canot easily find out.
# Therefore Search these versioned directories from newest to oldest to collect all the files we need.
vcRedistDirs = glob.glob(os.path.join(progFilesX86, r"Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.1*\onecore\x86\Microsoft.VC141.CRT"))
if len(vcRedistDirs)==0:
raise RuntimeError("Could not locate vc redistributables. Perhaps the Universal Windows Platform component in visual Studio is not installed")
vcRedistDirs.sort(reverse=True)
for fn in ("msvcp140.dll", "vccorlib140.dll", "vcruntime140.dll"):
fn = os.path.join(vcRedist, fn)
env.Install(sourceDir, fn)
for vcRedistDir in vcRedistDirs:
path = os.path.join(vcRedistDir, fn)
if os.path.isfile(path):
env.Install(sourceDir, path)
break
else:
raise RuntimeError("Could not locate %s. Perhaps the Universal Windows Platform component in visual Studio is not installed"%fn)

Return(['localWin10Lib'])
4 changes: 2 additions & 2 deletions nvdaHelper/remote/ime.cpp
Expand Up @@ -444,8 +444,8 @@ static LRESULT handleIMEWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LP
break;

case IMN_PRIVATE:
// Needed in XP to support EasyDots IME
if (!isUIElementMgrSafe || !isTSFThread(true))
// Needed to support EasyDots IME when TSF is not available
if (!isTSFThread(true))
handleReadingStringUpdate(hwnd);
break;
}
Expand Down
6 changes: 2 additions & 4 deletions nvdaHelper/remote/inputLangChange.cpp
Expand Up @@ -14,6 +14,7 @@ This license can be found at:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <VersionHelpers.h>
#include "nvdaHelperRemote.h"
#include "nvdaControllerInternal.h"
#include "ime.h"
Expand All @@ -38,10 +39,7 @@ LRESULT CALLBACK inputLangChange_callWndProcHook(int code, WPARAM wParam, LPARAM
}

void inputLangChange_inProcess_initialize() {
WORD version=LOWORD(GetVersion());
if(LOBYTE(version)>6||(LOBYTE(version)==6&&HIBYTE(version)>=2)) {
isWin8=true;
}
isWin8=IsWindows8OrGreater();
registerWindowsHook(WH_CALLWNDPROC,inputLangChange_callWndProcHook);
}

Expand Down
15 changes: 5 additions & 10 deletions nvdaHelper/remote/tsf.cpp
Expand Up @@ -28,7 +28,6 @@ This license can be found at:
using namespace std;

CLSID curTSFClsID={0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
bool isUIElementMgrSafe=false;


bool fetchRangeExtent(ITfRange* pRange, long* start, ULONG* length) {
Expand Down Expand Up @@ -182,13 +181,11 @@ bool TsfSink::Initialize() {
hr = src->AdviseSink(IID_ITfActiveLanguageProfileNotifySink,(ITfActiveLanguageProfileNotifySink*)this, &mLangProfCookie);
}
}
if(isUIElementMgrSafe) {
if (hr == S_OK) {
hr = mpThreadMgr->QueryInterface(IID_ITfUIElementMgr,(void**)&mpUIElementMgr);
}
if (hr == S_OK) {
hr = src->AdviseSink(IID_ITfUIElementSink,(ITfUIElementSink*)this, &mUIElementCookie);
}
if (hr == S_OK) {
hr = mpThreadMgr->QueryInterface(IID_ITfUIElementMgr,(void**)&mpUIElementMgr);
}
if (hr == S_OK) {
hr = src->AdviseSink(IID_ITfUIElementSink,(ITfUIElementSink*)this, &mUIElementCookie);
}
src->Release();
src = NULL;
Expand Down Expand Up @@ -647,8 +644,6 @@ TsfSink* fetchCurrentTsfSink() {
}

void TSF_inProcess_initialize() {
//Allow use of UIElementMgr on Vista and higher (crashes things on XP)
if((GetVersion()&0xff)>5) isUIElementMgrSafe=true;
// Initialize TLS and use window hook to create TSF sink in each thread
gTsfIndex = TlsAlloc();
if (gTsfIndex != TLS_OUT_OF_INDEXES)
Expand Down
1 change: 0 additions & 1 deletion nvdaHelper/remote/tsf.h
Expand Up @@ -20,6 +20,5 @@ void TSF_inProcess_terminate();
void TSF_thread_detached();
bool isTSFThread(bool checkProfile);
extern CLSID curTSFClsID;
extern bool isUIElementMgrSafe;

#endif
14 changes: 9 additions & 5 deletions readme.md
Expand Up @@ -36,12 +36,16 @@ The NVDA source depends on several other packages to run correctly.
The following dependencies need to be installed on your system:

* [Python](http://www.python.org/), version 2.7.13, 32 bit
* Microsoft Visual Studio Community 2015 with Update 3:
* To download, you will need to [join the Visual Studio Dev Essentials program](https://my.visualstudio.com/Benefits?wt.mc_id=o~msft~vscom~devessentials-hero~30569&campaign=o~msft~vscom~devessentials-hero~30569).
After you have joined, Visual Studio Community 2015 with Update 3 will be available on the Downloads tab.
* Microsoft Visual Studio 2017 Community, Version 15.3 or later:
* Download from https://www.visualstudio.com/downloads/
* When installing Visual Studio, you need to enable the following:
* In Visual C++: Common Tools for Visual C++ 2015, Windows XP Support for C++
* Windows and Web Development -> Universal Windows App Development Tools -> Tools (1.4.1) and Windows 10 SDK (10.0.14393)
On the Workloads tab, in the Windows group:
* Universal Windows Platform Development
* Desktop development with C++
* Then in the Summary list, under Desktop for C++, Optional grouping, ensure the following is selected:
* VC++ 2017 v141 toolset (x86,x64)
* Windows 10 SDK (10.0.15063.0) for Desktop C++ x86 and x64


### Git Submodules
Most of the dependencies are contained in Git submodules.
Expand Down
16 changes: 4 additions & 12 deletions sconstruct
Expand Up @@ -77,7 +77,7 @@ if "tests" in COMMAND_LINE_TARGETS:
vars.Add("unitTests", "A list of unit tests to run", "")

#Base environment for this and sub sconscripts
env = Environment(variables=vars,HOST_ARCH='x86',tools=["textfile","gettext","t2t",keyCommandsDocTool,'doxygen','recursiveInstall'])
env = Environment(variables=vars,HOST_ARCH='x86',tools=["textfile","gettextTool","t2t",keyCommandsDocTool,'doxygen','recursiveInstall'])

# speed up subsiquent runs by checking timestamps of targets and dependencies, and only using md5 if timestamps differ.
env.Decider('MD5-timestamp')
Expand All @@ -88,7 +88,7 @@ env.AddMethod(recursiveCopy)
#Check for any unknown variables
unknown=vars.UnknownVariables().keys()
if len(unknown)>0:
print "Unknown commandline variables: %s"%unknown
print("Unknown commandline variables: %s"%unknown)
Exit(1)

#Ensure that any Python subprocesses (such as for py2exe) can find our Python directory in miscDeps
Expand Down Expand Up @@ -128,7 +128,7 @@ if certPassword:
if certTimestampServer:
signExecCmd.extend(("/t", certTimestampServer))
def signExec(target,source,env):
print [str(x) for x in target]
print([str(x) for x in target])
#sys.exit(1)
# #3795: signtool can quite commonly fail with timestamping, so allow it to try up to 3 times with a 1 second delay between each try.
res=0
Expand All @@ -142,18 +142,12 @@ def signExec(target,source,env):
env['signExec']=signExec

#architecture-specific environments
archTools=['default','windowsSdk','midl','msrpc']
# MSVC analysis is only available in newer Windows SDKs
# So if required, remove the Windows SDK 7.1 (XP) tool
if 'analyze' in env['nvdaHelperDebugFlags']:
archTools.remove('windowsSdk')
archTools=['default','midl','msrpc']
env32=env.Clone(TARGET_ARCH='x86',tools=archTools)
env64=env.Clone(TARGET_ARCH='x86_64',tools=archTools)
# Hack around odd bug where some tool [after] msvc states that static and shared objects are different
env32['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
env64['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
# Environment for functionality that only works on Windows 10.
envWin10 = env.Clone(TARGET_ARCH='x86', tools=['default'])

env=env32

Expand All @@ -171,7 +165,6 @@ resFile=env.RES(target='build/nvda.res',
source=env.Substfile(target='build/nvda.rc', source='nvdaHelper/nvda.rc.subst', SUBST_DICT=projectRCSubstDict))
env32['projectResFile'] = resFile
env64['projectResFile'] = resFile
envWin10['projectResFile'] = resFile

#Fill sourceDir with anything provided for it by miscDeps
env.recursiveCopy(sourceDir,Dir('miscdeps/source'))
Expand All @@ -181,7 +174,6 @@ env.SConscript('source/comInterfaces_sconscript',exports=['env'])
#Process nvdaHelper scons files
env32.SConscript('nvdaHelper/archBuild_sconscript',exports={'env':env32,'clientInstallDir':clientDir.Dir('x86'),'libInstallDir':sourceLibDir},variant_dir='build/x86')
env64.SConscript('nvdaHelper/archBuild_sconscript',exports={'env':env64,'clientInstallDir':clientDir.Dir('x64'),'libInstallDir':sourceLibDir64},variant_dir='build/x86_64')
envWin10.SConscript('nvdaHelper/localWin10/sconscript', exports={'env': envWin10, 'libInstallDir': sourceLibDir}, variant_dir='build/x86/localWin10')

#Allow all NVDA's gettext po files to be compiled in source/locale
for po in env.Glob(sourceDir.path+'/locale/*/lc_messages/*.po'):
Expand Down
File renamed without changes.

0 comments on commit 58e1946

Please sign in to comment.