From c978544b7fca8e08fadcbc037d8c7d6441819c73 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Fri, 3 Aug 2018 11:11:04 -0400
Subject: [PATCH] project: fix cmake for visual studio project generation

- add helper script
- add project path to gitignore

Change-Id: I0ddc0ca3d8498471f444b6426bd8708f14d5d947
Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
---
 .gitignore     |   2 +
 CMakeLists.txt | 211 ++++++++++++++++++++++++++++---------------------
 make-lrc.bat   | 141 +++++++++++++++++++++++++++++++++
 3 files changed, 266 insertions(+), 88 deletions(-)
 create mode 100644 make-lrc.bat

diff --git a/.gitignore b/.gitignore
index d0afa985..c3070a78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
 .DS_Store
 build/
 build-local/
+
+msvc/
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7a22b6bd..284fdae8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,11 +20,24 @@ INCLUDE(GNUInstallDirs)
 INCLUDE(CMakePackageConfigHelpers)
 INCLUDE(GenerateExportHeader)
 
-ADD_DEFINITIONS(
-   ${QT_DEFINITIONS}
-   -fexceptions
-   -O2
-)
+option (ENABLE_SHARED "Build shared library" ON)
+
+string(SUBSTRING ${CMAKE_GENERATOR} 0 14 CMAKE_GENERATOR_SHORT)
+if(CMAKE_GENERATOR_SHORT MATCHES "Visual Studio ")
+    message(STATUS "Generating VS project")
+    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")
+endif()
+
+if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
+    ADD_DEFINITIONS(
+       ${QT_DEFINITIONS}
+       -fexceptions
+       -O2
+    )
+endif()
 
 # Options
 set(CHK_FREEABLE_BEFORE_ERASE_ACCOUNT_DESCRIPTION
@@ -83,39 +96,41 @@ IF((${ENABLE_TEST} MATCHES true))
   SET(ENABLE_LIBWRAP true) # because mocks use the same interface present in src/qtwrapper
 ENDIF()
 
+if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
 # Enable some useful warnings
-ADD_DEFINITIONS(
-   -Wall
-   -Wextra
-   -Wmissing-declarations
-   -Wmissing-noreturn
-   -Wpointer-arith
-   -Wcast-align
-   -Wwrite-strings
-   -Wformat-nonliteral
-   -Wformat-security
-   -Wswitch-enum
-   -Winit-self
-   -Wmissing-include-dirs
-   -Wundef
-   -Wmissing-format-attribute
-   -Wno-reorder
-   -Wunused
-   -Wuninitialized
-   -Woverloaded-virtual
-   -Wunused-value
-   -pedantic
-   -Wnonnull
-   -Wsequence-point
-   #-Wsystem-headers
-   -Wsizeof-pointer-memaccess
-   #-Wuseless-cast
-   -Wvarargs
-
-   #See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
-   -Wno-unused-function
-   -Wno-attributes
-)
+    ADD_DEFINITIONS(
+       -Wall
+       -Wextra
+       -Wmissing-declarations
+       -Wmissing-noreturn
+       -Wpointer-arith
+       -Wcast-align
+       -Wwrite-strings
+       -Wformat-nonliteral
+       -Wformat-security
+       -Wswitch-enum
+       -Winit-self
+       -Wmissing-include-dirs
+       -Wundef
+       -Wmissing-format-attribute
+       -Wno-reorder
+       -Wunused
+       -Wuninitialized
+       -Woverloaded-virtual
+       -Wunused-value
+       -pedantic
+       -Wnonnull
+       -Wsequence-point
+       #-Wsystem-headers
+       -Wsizeof-pointer-memaccess
+       #-Wuseless-cast
+       -Wvarargs
+
+       #See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
+       -Wno-unused-function
+       -Wno-attributes
+    )
+endif()
 
 #Add more warnings for compilers that support it. I used this command:
 #curl https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Warning-Options.html | \
@@ -198,7 +213,9 @@ IF(${ENABLE_LIBWRAP} MATCHES true)
 
    ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/src/qtwrapper)
    ADD_DEFINITIONS(-DENABLE_LIBWRAP=true) # Use native calls (no dbus)
-   ADD_DEFINITIONS(-Wno-unknown-pragmas)
+   if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
+      ADD_DEFINITIONS(-Wno-unknown-pragmas)
+   endif()
    SET(ENABLE_QT5 true) # Use Qt5
    MESSAGE(STATUS "Compiling with qtwrapper enabled, Qt5 enabled.")
 
@@ -235,16 +252,18 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src)
 INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_BINARY_DIR})
 
-# Build dbus api
-IF(DEFINED RING_XML_INTERFACES_DIR)
-    SET (dbus_xml_introspecs_path ${RING_XML_INTERFACES_DIR})
-ELSEIF(EXISTS "${RING_BUILD_DIR}/../bin/dbus")
-    SET (dbus_xml_introspecs_path ${RING_BUILD_DIR}/../bin/dbus)
-ELSE()
-    SET (dbus_xml_introspecs_path ${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces)
-ENDIF()
+IF(NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
+    # Build dbus api
+    IF(DEFINED RING_XML_INTERFACES_DIR)
+        SET (dbus_xml_introspecs_path ${RING_XML_INTERFACES_DIR})
+    ELSEIF(EXISTS "${RING_BUILD_DIR}/../bin/dbus")
+        SET (dbus_xml_introspecs_path ${RING_BUILD_DIR}/../bin/dbus)
+    ELSE()
+        SET (dbus_xml_introspecs_path ${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces)
+    ENDIF()
 
-MESSAGE(STATUS "Using Ring DBus-XML interfaces in ${dbus_xml_introspecs_path}")
+    MESSAGE(STATUS "Using Ring DBus-XML interfaces in ${dbus_xml_introspecs_path}")
+ENDIF()
 
 #File to compile
 SET( libringclient_LIB_SRCS
@@ -693,45 +712,57 @@ ENDIF()
 IF(NOT ${ENABLE_TEST} MATCHES true)
   QT5_WRAP_CPP(LIB_HEADER_MOC ${libringclient_PRIVATE_HDRS})
 ENDIF()
-ADD_LIBRARY( ringclient SHARED ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} )
 
 IF(NOT ${ENABLE_STATIC} MATCHES false)
-   ADD_LIBRARY( ringclient_static  STATIC ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} )
-   target_link_libraries(ringclient_static Qt5::Core)
-   TARGET_LINK_LIBRARIES( ringclient_static
-      -lpthread
-      ${QT_QTDBUS_LIBRARY}
-      ${QT_QTCORE_LIBRARY}
-      Qt5::Sql
-      )
-   SET_TARGET_PROPERTIES( ringclient_static
-      PROPERTIES VERSION ${GENERIC_LIB_VERSION}
-   )
+    message(STATUS "Configuring as static lib")
+    add_library( ringclient_static  STATIC ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} )
+    target_link_libraries(ringclient_static Qt5::Core)
+    target_link_libraries( ringclient_static
+       -lpthread
+       ${QT_QTDBUS_LIBRARY}
+       ${QT_QTCORE_LIBRARY}
+       Qt5::Sql
+       )
+    SET_TARGET_PROPERTIES( ringclient_static
+       PROPERTIES VERSION ${GENERIC_LIB_VERSION}
+    )
 ENDIF()
 
-target_link_libraries(ringclient Qt5::Core)
+if (ENABLE_SHARED)
+    message(STATUS "Configuring as shared lib")
+    add_library(ringclient SHARED ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} )
+    target_link_libraries(ringclient Qt5::Core)
+endif()
 
 IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  target_link_libraries(ringclient Qt5::DBus)
-  IF(NOT ${ENABLE_STATIC} MATCHES false)
+    if (ENABLE_SHARED)
+        target_link_libraries(ringclient Qt5::DBus)
+    endif()
+  IF(${ENABLE_STATIC} MATCHES true)
       target_link_libraries(ringclient_static Qt5::DBus)
   ENDIF()
 ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-   FIND_PACKAGE(Qt5Concurrent)
-
-   #For some reason, QSemaphore wont compile on Windows without QtConcurrent
-   target_link_libraries(ringclient Qt5::Concurrent)
+    FIND_PACKAGE(Qt5Concurrent)
+
+    #For some reason, QSemaphore wont compile on Windows without QtConcurrent
+    if(${ENABLE_STATIC} MATCHES true)
+        target_link_libraries(ringclient_static Qt5::Concurrent)
+    elseif(ENABLE_SHARED)
+        target_link_libraries(ringclient Qt5::Concurrent)
+    endif()
 ENDIF()
 
 
-TARGET_LINK_LIBRARIES( ringclient
-   -lpthread
-   ${QT_QTCORE_LIBRARY}
-   Qt5::Sql
-)
+IF (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+    TARGET_LINK_LIBRARIES( ringclient
+        -lpthread
+        ${QT_QTCORE_LIBRARY}
+        Qt5::Sql
+        )
+ENDIF()
 
 IF(${ENABLE_LIBWRAP} MATCHES true)
-   IF(NOT ${ring_BIN} MATCHES "ring_BIN-NOTFOUND")
+   IF((NOT ${ring_BIN} MATCHES "ring_BIN-NOTFOUND") AND (${ENABLE_STATIC} MATCHES false))
       TARGET_LINK_LIBRARIES( ringclient
          qtwrapper
          ${ring_BIN}
@@ -739,7 +770,7 @@ IF(${ENABLE_LIBWRAP} MATCHES true)
    ELSE()
       # Allow building with undefined symbols when only the daemon headers are provided
       # It speeds up our CI builds
-      IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+      IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
          SET_TARGET_PROPERTIES( ringclient PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
       ENDIF()
    ENDIF()
@@ -749,6 +780,7 @@ IF(${ENABLE_LIBWRAP} MATCHES true)
          ${ring_BIN}
       )
    ENDIF()
+
 ELSE()
    TARGET_LINK_LIBRARIES( ringclient
       ${QT_QTDBUS_LIBRARY}
@@ -767,9 +799,11 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
    ENDIF()
 ENDIF()
 
-SET_TARGET_PROPERTIES( ringclient
-  PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_VERSION}
-)
+if(${ENABLE_STATIC} MATCHES false)
+    SET_TARGET_PROPERTIES( ringclient
+      PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_VERSION}
+    )
+endif()
 
 SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include)
 
@@ -814,21 +848,22 @@ INSTALL( FILES ${libringclient_api_LIB_HDRS}
 #higher priority than the prefixed one.
 STRING(REPLACE "${CMAKE_LIBRARY_ARCHITECTURE}" "" SANE_LIBRARY_PATH "${CMAKE_INSTALL_FULL_LIBDIR}" )
 
-INSTALL( TARGETS ringclient
-  ARCHIVE DESTINATION ${SANE_LIBRARY_PATH}
-  RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
-  LIBRARY DESTINATION ${SANE_LIBRARY_PATH}
-  DESTINATION ${SANE_LIBRARY_PATH}
-)
-
 IF(NOT ${ENABLE_STATIC} MATCHES false)
-   INSTALL( TARGETS ringclient_static
-      ARCHIVE DESTINATION ${SANE_LIBRARY_PATH}
-      LIBRARY DESTINATION ${SANE_LIBRARY_PATH}
-      DESTINATION ${SANE_LIBRARY_PATH}
-   )
+    INSTALL( TARGETS ringclient_static
+        ARCHIVE DESTINATION ${SANE_LIBRARY_PATH}
+        LIBRARY DESTINATION ${SANE_LIBRARY_PATH}
+        DESTINATION ${SANE_LIBRARY_PATH}
+    )
 ENDIF()
 
+if(ENABLE_SHARED)
+    INSTALL( TARGETS ringclient
+        ARCHIVE DESTINATION ${SANE_LIBRARY_PATH}
+        RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+        LIBRARY DESTINATION ${SANE_LIBRARY_PATH}
+        DESTINATION ${SANE_LIBRARY_PATH}
+    )
+endif()
 
 SET(LIB_INSTALL_DIR ${SANE_LIBRARY_PATH})
 
diff --git a/make-lrc.bat b/make-lrc.bat
new file mode 100644
index 00000000..333aba3f
--- /dev/null
+++ b/make-lrc.bat
@@ -0,0 +1,141 @@
+:: Ring - native Windows LRC project generator
+
+@echo off
+setlocal
+
+if "%1" == "/?" goto Usage
+if "%~1" == "" goto Usage
+
+set doGen=N
+set doBuild=N
+
+set SCRIPTNAME=%~nx0
+
+if "%1"=="gen" (
+    set doGen=Y
+) else if "%1"=="build" (
+    set doBuild=Y
+) else (
+    goto Usage
+)
+
+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 (
+    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.15063.0
+    set Comp_x64=x86_amd64 10.0.15063.0
+) else (
+    set Comp_x86=amd64_x86 10.0.15063.0
+    set Comp_x64=amd64 10.0.15063.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
+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
+    set CMAKE_OPTIONS=-DQt5Core_DIR=!QtCmakeDir!\\Qt5Core -DQt5Sql_DIR=!QtCmakeDir!\\Qt5Sql -DQt5LinguistTools_DIR=!QtCmakeDir!\\Qt5LinguistTools -DQt5Concurrent_DIR=!QtCmakeDir!\\Qt5Concurrent -Dring_BIN=!DaemonDir!\MSVC\x86\ReleaseLib_win32\bin\dring.lib -DRING_INCLUDE_DIR=!DaemonDir!\src\dring
+) 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 -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     %0 [action] [architecture]
+echo:
+echo where
+echo:
+echo [action]           is: gen   ^| build
+echo [architecture]     is: x86   ^| x64
+echo:
+echo For example:
+echo     %SCRIPTNAME% gen x86     - gen x86 static lib vs projects for qtwrapper/lrc
+echo     %SCRIPTNAME% build x64   - build x64 qtwrapper/lrc static libs
+echo:
+goto :eof
+
+:cleanup
+endlocal
+exit /B %ERRORLEVEL%
\ No newline at end of file
-- 
GitLab