From 9033db9d3344bb569b111c9debc1426b746be0a7 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Fri, 20 Sep 2019 17:56:25 -0400
Subject: [PATCH] win32: use python build script

Change-Id: Id23b06ba630ca2be4c9ca6371edc27b54b91a488
---
 CMakeLists.txt               |   2 +-
 make-lrc.bat                 | 172 ----------------------
 make-lrc.py                  | 268 +++++++++++++++++++++++++++++++++++
 src/qtwrapper/CMakeLists.txt |   5 +-
 4 files changed, 273 insertions(+), 174 deletions(-)
 delete mode 100644 make-lrc.bat
 create mode 100644 make-lrc.py

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 797c6ed7..6286f593 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,7 @@ if(CMAKE_GENERATOR_SHORT MATCHES "Visual Studio ")
     set(CMAKE_CXX_COMPILER_ID "MSVC")
     set(ENABLE_TEST false)
     set(ENABLE_STATIC true)
-    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi /W0")
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi /W0 /MP")
 endif()
 
 if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
diff --git a/make-lrc.bat b/make-lrc.bat
deleted file mode 100644
index dd589e51..00000000
--- a/make-lrc.bat
+++ /dev/null
@@ -1,172 +0,0 @@
-:: Ring - native Windows LRC project generator
-
-@echo off
-if "%1" == "/?" goto Usage
-if "%~1" == "" goto Usage
-
-set doGen=N
-set doBuild=N
-
-set SCRIPTNAME=%~nx0
-
-if "%1"=="gen" (
-    set doGen=Y
-    set command=Generate
-) else if "%1"=="build" (
-    set doBuild=Y
-    set command=Build
-) else (
-    goto Usage
-)
-
-if "%doGen%"=="Y" (
-    if NOT "%4"=="" goto Version_New
-    goto Default_version
-) else (
-    goto StartLocal
-)
-
-:Version_New
-set QtDir=C:\\Qt\\%4%
-set Version=%4%
-if not exist "%QtDir%" echo This Qt path does not exist, using default version.
-if exist "%QtDir%" goto StartLocal
-:Default_version
-set QtDir=C:\\Qt\\5.9.4
-set Version=5.9.4
-if not exist "%QtDir%" echo Default Qt path does not exist, check your installation path. &goto Usage
-
-setlocal
-:StartLocal
-
-set arch=N
-
-shift
-:ParseArgs
-if "%1" == "" goto FinishedArgs
-if /I "%1"=="x86" (
-    set arch=x86
-) else if /I "%1"=="x64" (
-    set arch=x64
-) else if /I "%1"=="version" (
-    shift
-) else (
-    goto Usage
-)
-shift
-goto ParseArgs
-
-:FinishedArgs
-if "%arch%"=="x86" (
-    set MSBUILD_ARGS=/nologo /p:useenv=true /p:Configuration=Release /p:Platform=Win32 /verbosity:normal /maxcpucount:%NUMBER_OF_PROCESSORS%
-) else if "%arch%"=="x64" (
-    set MSBUILD_ARGS=/nologo /p:useenv=true /p:Configuration=Release /p:Platform=x64 /verbosity:normal /maxcpucount:%NUMBER_OF_PROCESSORS%
-)
-
-@setlocal
-
-set VSInstallerFolder="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"
-if %PROCESSOR_ARCHITECTURE%==x86 set VSInstallerFolder="%ProgramFiles%\Microsoft Visual Studio\Installer"
-
-pushd %VSInstallerFolder%
-for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (
-  set VSLATESTDIR=%%i
-)
-popd
-
-echo VS Installation folder: %VSLATESTDIR%
-
-if not exist "%VSLATESTDIR%\VC\Auxiliary\Build\vcvarsall.bat" (
-    echo:
-    echo VSInstallDir not found or not installed correctly.
-    goto cleanup
-)
-
-if %PROCESSOR_ARCHITECTURE%==x86 (
-    set Comp_x86=x86 10.0.16299.0
-    set Comp_x64=x86_amd64 10.0.16299.0
-) else (
-    set Comp_x86=amd64_x86 10.0.16299.0
-    set Comp_x64=amd64 10.0.16299.0
-)
-
-set path=%path:"=%
-if "%arch%"=="x86" (
-    call "%VSLATESTDIR%"\\VC\\Auxiliary\\Build\\vcvarsall.bat %Comp_x86%
-) else if "%arch%"=="x64" (
-    call "%VSLATESTDIR%"\\VC\\Auxiliary\\Build\\vcvarsall.bat %Comp_x64%
-)
-
-if "%arch%" neq "N" (
-    if "%doGen%" neq "N" (
-        goto genLRC
-    ) else if "%doBuild%" neq "N" (
-		goto buildLRC
-    )
-    goto :eof
-)
-goto Usage
-
-:genLRC
-echo Generating using Qt version: %Version%
-setlocal EnableDelayedExpansion
-set DaemonDir=%cd%\\..\\daemon
-mkdir msvc
-cd msvc
-set PATH=C:\\Program Files\\CMake\\bin\\;%PATH%
-if "echo QtDir is: %QtDir%"=="" (
-    echo Error: QtDir not specified
-    goto cleanup
-)
-set CMAKE_GENERATOR_STRING=""
-set CMAKE_OPTIONS=""
-if "%arch%"=="x86" (
-    set CMAKE_GENERATOR_STRING="Visual Studio 15 2017 Win32"
-    set QtCmakeDir=%QtDir%\\msvc2017\\lib\\cmake
-) else if "%arch%"=="x64" (
-    set CMAKE_GENERATOR_STRING="Visual Studio 15 2017 Win64"
-    set QtCmakeDir=%QtDir%\\msvc2017_64\\lib\\cmake
-)
-set CMAKE_OPTIONS=-DQt5Core_DIR=!QtCmakeDir!\\Qt5Core -DQt5Sql_DIR=!QtCmakeDir!\\Qt5Sql -DQt5LinguistTools_DIR=!QtCmakeDir!\\Qt5LinguistTools -DQt5Concurrent_DIR=!QtCmakeDir!\\Qt5Concurrent -DQt5Gui_DIR=!QtCmakeDir!\\Qt5Gui -Dring_BIN=!DaemonDir!\MSVC\x64\ReleaseLib_win32\bin\dring.lib -DRING_INCLUDE_DIR=!DaemonDir!\src\dring
-cmake .. -G !CMAKE_GENERATOR_STRING! !CMAKE_OPTIONS!
-endlocal
-goto cleanup
-
-:buildLRC
-:: build qtwrapper
-msbuild msvc\src\qtwrapper\qtwrapper.vcxproj %MSBUILD_ARGS%
-:: build lrc
-msbuild msvc\ringclient_static.vcxproj %MSBUILD_ARGS%
-goto cleanup
-
-@endlocal
-
-:Usage
-echo:
-echo The correct usage is:
-echo:
-echo     %SCRIPTNAME% [action] [architecture] [version] [version_para]
-echo:
-echo where
-echo:
-echo [action]           is: gen   ^| build
-echo [architecture]     is: x86   ^| x64
-echo [version]          is: version - optional
-echo [version_para]     is: 5.9.4 ^| Qt version installed
-echo:
-echo For example:
-echo     %SCRIPTNAME% gen x86                    - gen x86 static lib vs projects for qtwrapper/lrc for Qt version 5.9.4
-echo     %SCRIPTNAME% gen x86 version 5.12.0     - gen x86 static lib vs projects for qtwrapper/lrc for Qt version 5.12.0
-echo     %SCRIPTNAME% build x64                  - build x64 qtwrapper/lrc static libs
-echo:
-goto :eof
-
-:cleanup
-endlocal
-if %ERRORLEVEL% geq 1 (
-    echo %command% failed
-    exit %ERRORLEVEL%
-) else (
-    echo %command% succeeded
-    exit /B %ERRORLEVEL%
-)
diff --git a/make-lrc.py b/make-lrc.py
new file mode 100644
index 00000000..6a72d9e8
--- /dev/null
+++ b/make-lrc.py
@@ -0,0 +1,268 @@
+import tempfile
+import re
+import sys
+import os
+import subprocess
+import platform
+import argparse
+import multiprocessing
+import shutil
+import fileinput
+import re
+
+# vs help
+win_sdk_default = '10.0.16299.0'
+win_toolset_default = 'v141'
+
+vs_where_path = os.path.join(
+    os.environ['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer', 'vswhere.exe'
+)
+
+host_is_64bit = (False, True)[platform.machine().endswith('64')]
+
+
+def getLatestVSVersion():
+    args = [
+        '-latest',
+        '-products *',
+        '-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
+        '-property installationVersion'
+    ]
+    cmd = [vs_where_path] + args
+    output = subprocess.check_output(' '.join(cmd)).decode('utf-8')
+    if output:
+        return output.splitlines()[0].split('.')[0]
+    else:
+        return
+
+
+def findVSLatestDir():
+    args = [
+        '-latest',
+        '-products *',
+        '-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
+        '-property installationPath'
+    ]
+    cmd = [vs_where_path] + args
+    output = subprocess.check_output(' '.join(cmd)).decode('utf-8')
+    if output:
+        return output.splitlines()[0]
+    else:
+        return
+
+
+def findMSBuild():
+    filename = 'MSBuild.exe'
+    for root, _, files in os.walk(findVSLatestDir() + r'\\MSBuild'):
+        if filename in files:
+            return os.path.join(root, filename)
+
+
+def getVSEnv(arch='x64', platform='', version=''):
+    env_cmd = 'set path=%path:"=% && ' + \
+        getVSEnvCmd(arch, platform, version) + ' && set'
+    p = subprocess.Popen(env_cmd,
+                         shell=True,
+                         stdout=subprocess.PIPE)
+    stdout, _ = p.communicate()
+    out = stdout.decode('utf-8').split("\r\n")[5:-1]
+    return dict(s.split('=', 1) for s in out)
+
+
+def getCMakeGenerator(vs_version):
+    if vs_version == '15':
+        return 'Visual Studio 15 2017 Win64'
+    else:
+        return 'Visual Studio ' + vs_version + ' 2019'
+
+
+def getVSEnvCmd(arch='x64', platform='', version=''):
+    vcEnvInit = [findVSLatestDir() + r'\VC\Auxiliary\Build\"vcvarsall.bat']
+    if platform != '':
+        args = [arch, platform, version]
+    else:
+        args = [arch, version]
+    if args:
+        vcEnvInit.extend(args)
+    vcEnvInit = 'call \"' + ' '.join(vcEnvInit)
+    return vcEnvInit
+
+
+def build_project(msbuild, msbuild_args, proj, env_vars):
+    args = []
+    args.extend(msbuild_args)
+    args.append(proj)
+    cmd = [msbuild]
+    cmd.extend(args)
+    p = subprocess.Popen(cmd, shell=True,
+                         stdout=sys.stdout,
+                         env=env_vars)
+    _, perr = p.communicate()
+    if perr:
+        print("Build failed when building ", proj)
+        sys.exit(1)
+
+
+def purge_dir(build_dir):
+    if os.path.exists(build_dir):
+        try:
+            shutil.rmtree(build_dir)
+        except Exception as e:
+            print('Error while removing directory: ' + str(e))
+            sys.exit(1)
+
+
+def generate(force, qtver, sdk, toolset, arch):
+    # check build dir
+    this_dir = os.path.dirname(os.path.realpath(__file__))
+    build_dir = this_dir + '\\msvc'
+    if os.path.exists(build_dir):
+        if not force:
+            print("Skipping generate, build directory already exists!")
+            return
+        purge_dir(build_dir)
+    print('Generating lrc with Qt-' + qtver + ' ' +
+          arch + ' ' + sdk + ' ' + toolset)
+    this_dir = os.path.dirname(os.path.realpath(__file__))
+    daemon_dir = os.path.dirname(this_dir) + '\\daemon'
+    daemon_bin = daemon_dir + '\\MSVC\\x64\\ReleaseLib_win32\\bin\\dring.lib'
+    if not os.path.exists(daemon_bin):
+        print("Daemon library not found!")
+        sys.exit(1)
+    # we just assume Qt is installed in the default folder
+    qt_dir = 'C:\\Qt\\' + qtver
+    cmake_gen = getCMakeGenerator(getLatestVSVersion())
+    qt_cmake_dir = qt_dir + '\\msvc2017_64\\lib\\cmake\\'
+    cmake_options = [
+        '-DQt5Core_DIR=' + qt_cmake_dir + 'Qt5Core',
+        '-DQt5Sql_DIR=' + qt_cmake_dir + 'Qt5Sql',
+        '-DQt5LinguistTools_DIR=' + qt_cmake_dir + 'Qt5LinguistTools',
+        '-DQt5Concurrent_DIR=' + qt_cmake_dir + 'Qt5Concurrent',
+        '-DQt5Gui_DIR=' + qt_cmake_dir + 'Qt5Gui',
+        '-Dring_BIN=' + daemon_bin,
+        '-DRING_INCLUDE_DIR=' + daemon_dir + '\\src\\dring',
+        '-DCMAKE_SYSTEM_VERSION=' + sdk
+    ]
+    build_dir = this_dir + '\\msvc'
+    if not os.path.exists(build_dir):
+        os.makedirs(build_dir)
+    os.chdir(build_dir)
+    cmd = ['cmake', '..', '-G', cmake_gen]
+    cmd.extend(cmake_options)
+    p = subprocess.Popen(cmd, shell=True,
+                         stdout=subprocess.PIPE)
+    _, perr = p.communicate()
+    if perr:
+        print("Couldn't generate!")
+        sys.exit(1)
+
+    qtwrapper_proj_path = this_dir + '\\msvc\\src\\qtwrapper\\qtwrapper.vcxproj'
+    lrc_proj_path = this_dir + '\\msvc\\ringclient_static.vcxproj'
+
+    # force toolset
+    replace_vs_prop(qtwrapper_proj_path,
+                    'PlatformToolset',
+                    toolset)
+    replace_vs_prop(lrc_proj_path,
+                    'PlatformToolset',
+                    toolset)
+    # force unicode
+    replace_vs_prop(qtwrapper_proj_path,
+                    'CharacterSet',
+                    'Unicode')
+    replace_vs_prop(lrc_proj_path,
+                    'CharacterSet',
+                    'Unicode')
+    os.chdir(this_dir)
+
+
+def replace_vs_prop(filename, prop, val):
+    p = re.compile(r'(?s)<' + prop + r'\s?.*?>(.*?)<\/' + prop + r'>')
+    val = r'<' + prop + r'>' + val + r'</' + prop + r'>'
+    with fileinput.FileInput(filename, inplace=True) as file:
+        for line in file:
+            print(re.sub(p, val, line), end='')
+
+
+def build(arch, toolset):
+    print('Building lrc Release|' + arch)
+    vs_env_vars = {}
+    vs_env_vars.update(getVSEnv())
+    this_dir = os.path.dirname(os.path.realpath(__file__))
+    build_dir = this_dir + '\\msvc'
+    qtwrapper_proj_path = build_dir + '\\src\\qtwrapper\\qtwrapper.vcxproj'
+    lrc_proj_path = build_dir + '\\ringclient_static.vcxproj'
+    msbuild = findMSBuild()
+    if not os.path.isfile(msbuild):
+        raise IOError('msbuild.exe not found. path=' + msbuild)
+    msbuild_args = [
+        '/nologo',
+        '/verbosity:minimal',
+        '/maxcpucount:' + str(multiprocessing.cpu_count()),
+        '/p:Platform=' + arch,
+        '/p:Configuration=' + 'Release',
+        '/p:useenv=true',
+        '/p:PlatformToolset=' + toolset]
+    build_project(msbuild, msbuild_args, qtwrapper_proj_path, vs_env_vars)
+    build_project(msbuild, msbuild_args, lrc_proj_path, vs_env_vars)
+
+
+def parse_args():
+    ap = argparse.ArgumentParser(description="Windows Jami-lrc build tool")
+    ap.add_argument(
+        '-b', '--build', action='store_true',
+        help='Build lrc')
+    ap.add_argument(
+        '-f', '--force', action='store_true',
+        help='Force action')
+    ap.add_argument(
+        '-p', '--purge', action='store_true',
+        help='Purges the build directory')
+    ap.add_argument(
+        '-q', '--qtver', default='5.9.4',
+        help='Sets the Qt version to build with')
+    ap.add_argument(
+        '-g', '--gen', action='store_true',
+        help='Generates vs project files for lrc using CMake')
+    ap.add_argument(
+        '-a', '--arch', default='x64',
+        help='Sets the build architecture')
+    ap.add_argument(
+        '-s', '--sdk', default=win_sdk_default, type=str,
+        help='Use specified windows sdk version')
+    ap.add_argument(
+        '-t', '--toolset', default=win_toolset_default, type=str,
+        help='Use specified platform toolset version')
+
+    parsed_args = ap.parse_args()
+
+    return parsed_args
+
+
+def main():
+    if not host_is_64bit:
+        print('These scripts will only run on a 64-bit Windows system for now!')
+        sys.exit(1)
+
+    if int(getLatestVSVersion()) < 15:
+        print('These scripts require at least Visual Studio v15 2017!')
+        sys.exit(1)
+
+    parsed_args = parse_args()
+
+    if parsed_args.purge:
+        print('Purging build dir')
+        this_dir = os.path.dirname(os.path.realpath(__file__))
+        build_dir = this_dir + '\\msvc'
+        purge_dir(build_dir)
+
+    if parsed_args.gen:
+        generate(parsed_args.force, parsed_args.qtver,
+                 parsed_args.sdk, parsed_args.toolset, parsed_args.arch)
+
+    if parsed_args.build:
+        build(parsed_args.arch, parsed_args.toolset)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/qtwrapper/CMakeLists.txt b/src/qtwrapper/CMakeLists.txt
index b03a441f..a10919ab 100644
--- a/src/qtwrapper/CMakeLists.txt
+++ b/src/qtwrapper/CMakeLists.txt
@@ -10,7 +10,6 @@ MESSAGE("Compiling with qtwrapper")
 
 SET(ENABLE_LIBWRAP true)
 ADD_DEFINITIONS(-DENABLE_LIBWRAP=true)
-ADD_DEFINITIONS("-std=c++0x")
 
 SET(LOCAL_CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/../../cmake/)
 SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LOCAL_CMAKE_MODULE_PATH})
@@ -51,6 +50,10 @@ IF(NOT ${ring_BIN} MATCHES "ring_BIN-NOTFOUND")
    )
 ENDIF()
 
+if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
+   ADD_DEFINITIONS("-std=c++0x")
+endif()
+
 IF (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /U_MBCS /DUNICODE")
 ENDIF()
\ No newline at end of file
-- 
GitLab