From 6e80780d1720bb23109c98f23eb7fc12ddafd56e Mon Sep 17 00:00:00 2001
From: Davide Gerhard <rainbow@irh.it>
Date: Fri, 24 May 2019 08:32:40 +0200
Subject: [PATCH] cmake: windows fixes for MSVC

- disable sdrangelbench on windows with MSVC
- fix cpu flags test code for MSVC
- add ico file
---
 CMakeLists.txt                         | 119 ++++++++++++++++++-----
 cmake/Modules/FindCPUflags.cmake       | 103 +++++++++++++++-----
 cmake/Modules/QtLocator.cmake          |  41 ++++++++
 cmake/cpack/CMakeLists.txt             |  43 +++++++--
 cmake/cpack/sdrangel_icon.ico          | Bin 0 -> 106124 bytes
 cmake/test/test_arm_neon.cxx           |   2 +-
 cmake/test/test_x86_avx.cxx            |   1 +
 cmake/test/test_x86_avx2.cxx           |   1 +
 cmake/test/test_x86_avx512.cxx         |   1 +
 cmake/test/test_x86_sse2.cxx           |   1 +
 cmake/test/test_x86_sse3.cxx           |   1 +
 cmake/test/test_x86_sse41.cxx          |   1 +
 cmake/test/test_x86_sse42.cxx          |   1 +
 cmake/test/test_x86_ssse3.cxx          |   1 +
 external/CMakeLists.txt                | 125 +++++++++++++++++++------
 external/windows                       |   2 +-
 plugins/CMakeLists.txt                 |  26 ++++-
 plugins/channelrx/CMakeLists.txt       |   4 +
 plugins/samplesink/localoutput/ccc.txt |  50 ----------
 sdrbase/plugin/pluginmanager.cpp       |   2 +
 sdrsrv/CMakeLists.txt                  |  25 ++---
 21 files changed, 395 insertions(+), 155 deletions(-)
 create mode 100644 cmake/Modules/QtLocator.cmake
 create mode 100644 cmake/cpack/sdrangel_icon.ico
 delete mode 100644 plugins/samplesink/localoutput/ccc.txt

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6722ded8..9b90e48c5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,11 @@
 cmake_minimum_required(VERSION 3.1.0)
 
+# force 64bit on windows because we have only that library
+# TODO discuss because, at this days, a dsp software should be 64bit
+if(WIN32 AND NOT CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER)
+  set(CMAKE_GENERATOR_PLATFORM "x64" CACHE INTERNAL "")
+endif()
+
 project(sdrangel)
 
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
@@ -92,11 +98,8 @@ set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_BINARY_DIR};/.git/;.gitignore;menu.yml;
 set(CPACK_SOURCE_GENERATOR "ZIP;TGZ")
 
 # if we don't set build_type
-if(NOT DEFINED CMAKE_BUILD_TYPE OR
-    "${CMAKE_BUILD_TYPE}" STREQUAL "" OR
-    "${CMAKE_BUILD_TYPE}" STREQUAL "MacPorts" OR
-    "${CMAKE_BUILD_TYPE}" STREQUAL "None")
-  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
+if(NOT DEFINED CMAKE_BUILD_TYPE OR "${CMAKE_BUILD_TYPE}" STREQUAL "")
+      set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
 endif()
 message(STATUS "Build type set to: ${CMAKE_BUILD_TYPE}")
 
@@ -106,14 +109,26 @@ if(NOT DEBUG_OUTPUT)
 endif()
 
 # declare build structures
-# !! change sdrbase/plugin/pluginmanager.cpp too !!
+# !! change sdrbase/plugins/pluginmanager.cpp too !!
+set(SDRANGEL_BINARY_BIN_DIR "${CMAKE_BINARY_DIR}/bin")
+set(SDRANGEL_BINARY_LIB_DIR "${CMAKE_BINARY_DIR}/lib")
 if(WIN32)
-  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${SDRANGEL_BINARY_BIN_DIR}")
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
 else()
   set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
 endif()
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${SDRANGEL_BINARY_LIB_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${SDRANGEL_BINARY_LIB_DIR}")
+if(WIN32)
+  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
+  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
+  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
+  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
+  set(BUILD_PLUGINS_RUNTIME_DIR "${SDRANGEL_BINARY_BIN_DIR}/plugins")
+  set(BUILD_PLUGINSSRV_RUNTIME_DIR "${SDRANGEL_BINARY_BIN_DIR}/pluginssrv")
+endif()
 set(BUILD_PLUGINS_DIR "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins")
 set(BUILD_PLUGINSSRV_DIR "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pluginssrv")
 # use only lib when create .app/.dmg
@@ -159,15 +174,53 @@ elseif(APPLE)
   configure_file("${CMAKE_SOURCE_DIR}/cmake/cpack/MacOSXBundleInfo.plist.in"
     "${CMAKE_BINARY_DIR}/Info.plist" @ONLY)
 elseif (WIN32)
+  # check compiler version
+  if(MSVC_VERSION GREATER 1919 AND MSVC_VERSION LESS 1910)
+    message(FATAL_ERROR "You must use Microsoft Visual Studio 2017 as compiler, aka MSVC 14.1")
+  endif()
+
+  # used on code but not defined on VS2017
+  add_definitions(-D__WINDOWS__)
+
+  # compile with full multicore
+  set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+
+  # find Qt folder
+  include(QtLocator)
+
+  # in alternative we can use ExternalProject
   set(EXTERNAL_LIBRARY_FOLDER "${CMAKE_SOURCE_DIR}/external/windows")
   set(BOOST_ROOT "${EXTERNAL_LIBRARY_FOLDER}/boost" CACHE INTERNAL "")
   set(FFTW3F_FOUND ON CACHE INTERNAL "")
   set(FFTW3F_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/fftw-3/include" CACHE INTERNAL "")
-  set(FFTW3F_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/fftw-3/libfftw3f-3.dll" CACHE INTERNAL "")
+  set(FFTW3F_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/fftw-3/libfftw3f-3.lib" CACHE INTERNAL "")
   set(LIBUSB_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/libusb/include" CACHE INTERNAL "")
-  set(LIBUSB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/libusb/libusb-1.0.x64.dll" CACHE INTERNAL "")
+  set(LIBUSB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/libusb/MS64/dll/libusb-1.0.lib" CACHE INTERNAL "")
   set(OpenCV_DIR "${EXTERNAL_LIBRARY_FOLDER}/opencv" CACHE INTERNAL "")
   set(PKG_CONFIG_EXECUTABLE "${EXTERNAL_LIBRARY_FOLDER}/pkg-config-lite/bin/pkg-config.exe" CACHE INTERNAL "")
+
+  # ffmpeg
+  set(FFMPEG_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  #set(FFMPEG_LIBRARIES)
+  set(AVCODEC_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  set(AVCODEC_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/avcodec.lib" CACHE INTERNAL "")
+  set(AVFORMAT_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  set(AVFORMAT_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/avformat.lib" CACHE INTERNAL "")
+  set(AVUTIL_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  set(AVUTIL_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/avutil.lib" CACHE INTERNAL "")
+  set(SWRESAMPLE_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  set(SWRESAMPLE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/swresample.lib" CACHE INTERNAL "")
+  set(SWSCALE_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
+  set(SWSCALE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/swscale.lib" CACHE INTERNAL "")
+
+  # used on fixup_bundle phase
+  set(WINDOWS_FIXUP_BUNDLE_LIB_DIRS
+    "${Qt5_DIR}/../../../bin"
+    "${EXTERNAL_LIBRARY_FOLDER}/fftw-3"
+    "${EXTERNAL_LIBRARY_FOLDER}/libusb/MS64/dll"
+    "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/bin"
+  )
 endif()
 
 # TODO: check if(DEFINED) and fix macports -D
@@ -246,7 +299,22 @@ find_package(PkgConfig REQUIRED)
 find_package(Boost REQUIRED)
 find_package(FFTW3F REQUIRED)
 find_package(LibUSB REQUIRED)  # used by so many packages
-find_package(OpenCV) # channeltx/modatv
+find_package(OpenCV REQUIRED core highgui imgproc) # channeltx/modatv
+
+# unfortunately OpenCV library from windows doesn't set the cache option
+if(WIN32)
+  set(OpenCV_INCLUDE_DIRS "${OpenCV_INCLUDE_DIRS}" CACHE INTERNAL "")
+  set(OpenCV_LIBS "${OpenCV_LIBS}" CACHE INTERNAL "")
+
+  # add libs folder for fixup_bundle()
+  get_filename_component(GFN_Boost_LIBS_DIR Boost_LIBS DIRECTORY)
+  get_filename_component(GFN_OpenCV_LIBS_DIR OpenCV_LIBS DIRECTORY)
+  set(WINDOWS_FIXUP_BUNDLE_LIB_DIRS
+    "${WINDOWS_FIXUP_BUNDLE_LIB_DIRS}"
+    "${GFN_Boost_LIBS_DIR}"
+    "${GFN_OpenCV_LIBS_DIR}"
+  )
+endif()
 
 # macOS compatibility
 if(APPLE)
@@ -310,13 +378,19 @@ endif()
 
 # base libraries
 add_subdirectory(sdrbase)
-add_subdirectory(sdrbench)
 add_subdirectory(httpserver)
 add_subdirectory(logging)
 add_subdirectory(qrtplib)
 add_subdirectory(swagger)
 add_subdirectory(devices)
 
+# strange symbol dependency
+#  mainbench.obj : error LNK2001: unresolved external
+#  symbol "public: static float const decimation_scale<12>::scaleIn" (?scaleIn@?$decimation_scale@$0M@@@2MB)
+if(NOT WIN32)
+  add_subdirectory(sdrbench)
+endif()
+
 if (BUILD_GUI)
     add_subdirectory(sdrgui)
     add_subdirectory(plugins plugins)
@@ -343,20 +417,21 @@ include_directories(
 )
 
 ############ build sdrangel benchmark ################
-set(sdrangelbench_SOURCES
+if(NOT WIN32)
+  set(sdrangelbench_SOURCES
     appbench/main.cpp
-)
+  )
 
-add_executable(sdrangelbench
+  add_executable(sdrangelbench
     ${sdrangelbench_SOURCES}
-)
+  )
 
-target_link_libraries(sdrangelbench
+  target_link_libraries(sdrangelbench
     Qt5::Multimedia
     sdrbench
     logging
-)
-
+  )
+endif()
 ############ build sdrangel gui ################
 if (BUILD_GUI)
     set(sdrangel_SOURCES
@@ -397,7 +472,9 @@ if (BUILD_SERVER)
 endif()
 
 ############ install ##################
-install(TARGETS sdrangelbench DESTINATION ${INSTALL_BIN_DIR})
+if(NOT WIN32)
+  install(TARGETS sdrangelbench DESTINATION ${INSTALL_BIN_DIR})
+endif()
 if (BUILD_GUI)
       install(TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${INSTALL_BIN_DIR})
 endif()
diff --git a/cmake/Modules/FindCPUflags.cmake b/cmake/Modules/FindCPUflags.cmake
index 46a1cd67f..34b5a2289 100644
--- a/cmake/Modules/FindCPUflags.cmake
+++ b/cmake/Modules/FindCPUflags.cmake
@@ -74,9 +74,11 @@ if (${ARCHITECTURE} MATCHES "x86_64|x86" AND (FORCE_SSSE3 OR FORCE_SSE41))
            add_definitions(-DUSE_SSSE3)
            add_definitions(-DUSE_SSE4_1)
        elseif(C_MSVC)
+           # seems that from MSVC 2015 comiler doesn't support those flags
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE4_1" )
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSE4_1" )
            set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
+           message(STATUS "Use SSE 4.1 SIMD instructions")
            add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_SSSE3)
            add_definitions(-DUSE_SSE4_1)
@@ -84,12 +86,16 @@ if (${ARCHITECTURE} MATCHES "x86_64|x86" AND (FORCE_SSSE3 OR FORCE_SSE41))
     endif()
 else ()
 if (${ARCHITECTURE} MATCHES "x86_64|x86")
-    try_run(RUN_SSE2 COMPILE_SSE2 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_sse2.cxx COMPILE_DEFINITIONS -msse2 -O0)
+    if(C_MSVC)
+       try_run(RUN_SSE2 COMPILE_SSE2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse2.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+       try_run(RUN_SSE2 COMPILE_SSE2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse2.cxx" COMPILE_DEFINITIONS -msse2 -O0)
+    endif()
     if(COMPILE_SSE2 AND RUN_SSE2 EQUAL 0)
        set(HAS_SSE2 ON CACHE BOOL "Architecture has SSSE2 SIMD enabled")
+       message(STATUS "Use SSE2 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2" )
-           message(STATUS "Use SSE2 SIMD instructions")
            add_definitions(-DUSE_SSE2)
        elseif(C_MSVC)
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE2" )
@@ -101,35 +107,46 @@ if (${ARCHITECTURE} MATCHES "x86_64|x86")
     else()
        set(HAS_SSE2 OFF CACHE BOOL "Architecture does not have SSSE2 SIMD enabled")
     endif()
-    try_run(RUN_SSSE3 COMPILE_SSSE3 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_ssse3.cxx COMPILE_DEFINITIONS -mssse3 -O0)
+    if(C_MSVC)
+        try_run(RUN_SSSE3 COMPILE_SSSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_ssse3.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_SSSE3 COMPILE_SSSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_ssse3.cxx" COMPILE_DEFINITIONS -mssse3 -O0)
+    endif()
     if(COMPILE_SSSE3 AND RUN_SSSE3 EQUAL 0)
        set(HAS_SSSE3 ON CACHE BOOL "Architecture has SSSE3 SIMD enabled")
+       message(STATUS "Use SSSE3 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mssse3" )
-           message(STATUS "Use SSSE3 SIMD instructions")
            add_definitions(-DUSE_SSSE3)
        elseif(C_MSVC)
-           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSSE3" )
-           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSSE3" )
+           # seems not present on MSVC 2017
+           #set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSSE3" )
+           #set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSSE3" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox" )
            set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
-           message(STATUS "Use MSVC SSSE3 SIMD instructions")
            add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_SSSE3)
        endif()
     else()
        set(HAS_SSSE3 OFF CACHE BOOL "Architecture does not have SSSE3 SIMD enabled")
     endif()
-    try_run(RUN_SSE4_1 COMPILE_SSE4_1 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_sse41.cxx COMPILE_DEFINITIONS -msse4.1 -O0)
+    if(C_MSVC)
+        try_run(RUN_SSE4_1 COMPILE_SSE4_1 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse41.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_SSE4_1 COMPILE_SSE4_1 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse41.cxx" COMPILE_DEFINITIONS -msse4.1 -O0)
+    endif()
     if(COMPILE_SSE4_1 AND RUN_SSE4_1 EQUAL 0)
        set(HAS_SSE4_1 ON CACHE BOOL "Architecture has SSE 4.1 SIMD enabled")
+       message(STATUS "Use SSE 4.1 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse4.1" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse4.1" )
-           message(STATUS "Use SSE 4.1 SIMD instructions")
            add_definitions(-DUSE_SSE4_1)
        elseif(C_MSVC)
-           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE4_1" )
-           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSE4_1" )
+           # seems not present on MSVC 2017
+           #set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE4_1" )
+           #set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSE4_1" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox" )
            set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
            add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_SSE4_1)
@@ -137,17 +154,23 @@ if (${ARCHITECTURE} MATCHES "x86_64|x86")
     else()
        set(HAS_SSE4_1 OFF CACHE BOOL "Architecture does not have SSE 4.1 SIMD enabled")
     endif()
-    try_run(RUN_SSE4_2 COMPILE_SSE4_2 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_sse42.cxx COMPILE_DEFINITIONS -msse4.2 -O0)
+    if(C_MSVC)
+        try_run(RUN_SSE4_2 COMPILE_SSE4_2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse42.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_SSE4_2 COMPILE_SSE4_2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse42.cxx" COMPILE_DEFINITIONS -msse4.2 -O0)
+    endif()
     if(COMPILE_SSE4_2 AND RUN_SSE4_2 EQUAL 0)
        set(HAS_SSE4_2 ON CACHE BOOL "Architecture has SSE 4.2 SIMD enabled")
+       message(STATUS "Use SSE 4.2 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse4.2" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse4.2" )
-           message(STATUS "Use SSE 4.2 SIMD instructions")
            add_definitions(-DUSE_SSE4_2)
        elseif(C_MSVC)
-           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE4_2" )
-           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSE4_2" )
+           # seems not present on MSVC 2017
+           #set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:SSE4_2" )
+           #set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:SSE4_2" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox" )
            set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
            add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_SSE4_2)
@@ -155,50 +178,84 @@ if (${ARCHITECTURE} MATCHES "x86_64|x86")
     else()
        set(HAS_SSE4_2 OFF CACHE BOOL "Architecture does not have SSE 4.2 SIMD enabled")
     endif()
-    try_run(RUN_AVX COMPILE_AVX ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_avx.cxx COMPILE_DEFINITIONS -mavx -O0)
+    if(C_MSVC)
+        try_run(RUN_AVX COMPILE_AVX "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_AVX COMPILE_AVX "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx.cxx" COMPILE_DEFINITIONS -mavx -O0)
+    endif()
     if(COMPILE_AVX AND RUN_AVX EQUAL 0)
        set(HAS_AVX ON CACHE BOOL "Architecture has AVX SIMD enabled")
+       message(STATUS "Use AVX SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mavx" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mavx" )
-           message(STATUS "Use AVX SIMD instructions")
+           add_definitions(-DUSE_AVX)
+       elseif(C_MSVC)
+           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:AVX" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:AVX" )
+           set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
+           add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_AVX)
        endif()
     else()
        set(HAS_AVX OFF CACHE BOOL "Architecture does not have AVX SIMD enabled")
     endif()
-    try_run(RUN_AVX2 COMPILE_AVX2 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_avx2.cxx COMPILE_DEFINITIONS -mavx2 -O0)
+    if(C_MSVC)
+        try_run(RUN_AVX2 COMPILE_AVX2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx2.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_AVX2 COMPILE_AVX2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx2.cxx" COMPILE_DEFINITIONS -mavx2 -O0)
+    endif()
     if(COMPILE_AVX2 AND RUN_AVX2 EQUAL 0)
        set(HAS_AVX2 ON CACHE BOOL "Architecture has AVX2 SIMD enabled")
+       message(STATUS "Use AVX2 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mavx2" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mavx2" )
-           message(STATUS "Use AVX2 SIMD instructions")
+           add_definitions(-DUSE_AVX2)
+       elseif(C_MSVC)
+           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:AVX2" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:AVX2" )
+           set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
+           add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_AVX2)
        endif()
     else()
        set(HAS_AVX2 OFF CACHE BOOL "Architecture does not have AVX2 SIMD enabled")
     endif()
-    try_run(RUN_AVX512 COMPILE_AVX512 ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_x86_avx512.cxx COMPILE_DEFINITIONS -mavx512f -O0)
+    if(C_MSVC)
+        try_run(RUN_AVX512 COMPILE_AVX512 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx512.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_AVX512 COMPILE_AVX512 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx512.cxx" COMPILE_DEFINITIONS -mavx512f -O0)
+    endif()
     if(COMPILE_AVX512 AND RUN_AVX512 EQUAL 0)
        set(HAS_AVX512 ON CACHE BOOL "Architecture has AVX512 SIMD enabled")
+       message(STATUS "Use AVX512 SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mavx512f" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mavx512f" )
-           message(STATUS "Use AVX512 SIMD instructions")
+           add_definitions(-DUSE_AVX512)
+       elseif(C_MSVC)
+           set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /arch:AVX512" )
+           set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox /arch:AVX512" )
+           set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
+           add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
            add_definitions(-DUSE_AVX512)
        endif()
     else()
        set(HAS_AVX512 OFF CACHE BOOL "Architecture does not have AVX512 SIMD enabled")
     endif()
 elseif(ARCHITECTURE_ARM)
-    try_run(RUN_NEON COMPILE_NEON ${CMAKE_BINARY_DIR}/tmp ${TEST_DIR}/test_arm_neon.cxx COMPILE_DEFINITIONS -mfpu=neon -O0)
+    if(C_MSVC)
+        try_run(RUN_NEON COMPILE_NEON "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_arm_neon.cxx" COMPILE_DEFINITIONS /O0)
+    else()
+        try_run(RUN_NEON COMPILE_NEON "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_arm_neon.cxx" COMPILE_DEFINITIONS -mfpu=neon -O0)
+    endif()
     if(COMPILE_NEON AND RUN_NEON EQUAL 0)
        set(HAS_NEON ON CACHE BOOL "Architecture has NEON SIMD enabled")
+       message(STATUS "Use NEON SIMD instructions")
        if(C_GCC OR C_CLANG)
            set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpu=neon" )
            set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mfpu=neon" )
-           message(STATUS "Use NEON SIMD instructions")
            add_definitions(-DUSE_NEON)
        endif()
     else()
diff --git a/cmake/Modules/QtLocator.cmake b/cmake/Modules/QtLocator.cmake
new file mode 100644
index 000000000..1403bbbb5
--- /dev/null
+++ b/cmake/Modules/QtLocator.cmake
@@ -0,0 +1,41 @@
+SET(QT_MISSING True)
+# msvc only; mingw will need different logic
+IF(MSVC)
+    # look for user-registry pointing to qtcreator
+    GET_FILENAME_COMPONENT(QT_BIN [HKEY_CURRENT_USER\\Software\\Classes\\Applications\\QtProject.QtCreator.cpp\\shell\\Open\\Command] PATH)
+
+    # get root path so we can search for 5.3, 5.4, 5.5, etc
+    STRING(REPLACE "/Tools" ";" QT_BIN "${QT_BIN}")
+    LIST(GET QT_BIN 0 QT_BIN)
+    FILE(GLOB QT_VERSIONS "${QT_BIN}/5.*")
+    LIST(SORT QT_VERSIONS)
+
+    # assume the latest version will be last alphabetically
+    LIST(REVERSE QT_VERSIONS)
+
+    LIST(GET QT_VERSIONS 0 QT_VERSION)
+
+    # fix any double slashes which seem to be common
+    STRING(REPLACE "//" "/"  QT_VERSION "${QT_VERSION}")
+
+    # do some math trickery to guess folder
+    # - qt uses (e.g.) "msvc2012"
+    # - cmake uses (e.g.) "1800"
+    # - see also https://cmake.org/cmake/help/v3.0/variable/MSVC_VERSION.html
+    MATH(EXPR QT_MSVC "2000 + (${MSVC_VERSION} - 200) / 100")
+
+    # check for 64-bit os
+    # may need to be removed for older compilers as it wasn't always offered
+    IF(CMAKE_SYSTEM_PROCESSOR MATCHES 64)
+        SET(QT_MSVC "${QT_MSVC}_64")
+    ENDIF()
+    SET(QT_PATH "${QT_VERSION}/msvc${QT_MSVC}")
+    SET(QT_MISSING False)
+ENDIF()
+
+# use Qt_DIR approach so you can find Qt after cmake has been invoked
+IF(NOT QT_MISSING)
+    MESSAGE("-- Qt found: ${QT_PATH}")
+    SET(Qt5_DIR "${QT_PATH}/lib/cmake/Qt5/")
+    SET(Qt5Test_DIR "${QT_PATH}/lib/cmake/Qt5Test")
+ENDIF()
diff --git a/cmake/cpack/CMakeLists.txt b/cmake/cpack/CMakeLists.txt
index f320170b1..10ae39500 100644
--- a/cmake/cpack/CMakeLists.txt
+++ b/cmake/cpack/CMakeLists.txt
@@ -171,15 +171,44 @@ elseif(LINUX AND BUNDLE)
     set (CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
   endif (RPMBUILDER)
 
-elseif((WIN32 OR MINGW) AND BUNDLE)
+elseif(WIN32 OR MINGW)
 
-  #set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
+  # Copy Qt Plugins; fixup_bundle doesn't do that
+  install (
+    DIRECTORY
+    "${QT_PLUGINS_DIR}/platforms"
+    "${QT_PLUGINS_DIR}/audio"
+    "${QT_PLUGINS_DIR}/accessible"
+    "${QT_PLUGINS_DIR}/imageformats"
+    "${QT_PLUGINS_DIR}/mediaservice"
+    "${QT_PLUGINS_DIR}/playlistformats"
+    "${QT_PLUGINS_DIR}/styles"
+    "${QT_PLUGINS_DIR}/iconengines"
+    DESTINATION "${SDRANGEL_BINARY_BIN_DIR}"
+    CONFIGURATIONS Release MinSizeRel
+    COMPONENT runtime
+    FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}"
+    PATTERN "*minimal*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+    PATTERN "*offscreen*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+    PATTERN "*quick*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+    PATTERN "*_debug${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+    )
 
-  list(APPEND CPACK_GENERATOR "NSIS")
-  set(CPACK_NSIS_PACKAGE_NAME "${APPLICATION_NAME}")
-  set(CPACK_NSIS_CONTACT "${APPLICATION_MAINTAINER}")
-  set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
-  set(CPACK_NSIS_MODIFY_PATH ON)
+install(CODE "
+  include(BundleUtilities)
+  fixup_bundle("${SDRANGEL_BINARY_BIN_DIR}" "" "${WINDOWS_FIXUP_BUNDLE_LIB_DIRS}")
+" COMPONENT Runtime)
+
+  if(BUNDLE)
+
+    set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
+
+    list(APPEND CPACK_GENERATOR "ZIP;NSIS")
+    set(CPACK_NSIS_PACKAGE_NAME "${APPLICATION_NAME}")
+    set(CPACK_NSIS_CONTACT "${APPLICATION_MAINTAINER}")
+    set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
+    set(CPACK_NSIS_MODIFY_PATH ON)
+  endif()
 
 endif(APPLE AND BUNDLE AND BUILD_GUI)
 
diff --git a/cmake/cpack/sdrangel_icon.ico b/cmake/cpack/sdrangel_icon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..62c7de726d8e000f4ca61a7f2d2bcd1fa7bd971d
GIT binary patch
literal 106124
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
ClseY{

literal 0
HcmV?d00001

diff --git a/cmake/test/test_arm_neon.cxx b/cmake/test/test_arm_neon.cxx
index f0e7dea33..cb48159ff 100644
--- a/cmake/test/test_arm_neon.cxx
+++ b/cmake/test/test_arm_neon.cxx
@@ -1,5 +1,5 @@
-#include <arm_neon.h>
 #include <stdint.h>
+#include <arm_neon.h>
 #include <stdlib.h>
 #include <signal.h>
 
diff --git a/cmake/test/test_x86_avx.cxx b/cmake/test/test_x86_avx.cxx
index 15a9bb7ea..2344fbcbe 100644
--- a/cmake/test/test_x86_avx.cxx
+++ b/cmake/test/test_x86_avx.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <immintrin.h>
 
 void signalHandler(int signum) {
diff --git a/cmake/test/test_x86_avx2.cxx b/cmake/test/test_x86_avx2.cxx
index 48f447372..369186de7 100644
--- a/cmake/test/test_x86_avx2.cxx
+++ b/cmake/test/test_x86_avx2.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <immintrin.h>
 
 void signalHandler(int signum) {
diff --git a/cmake/test/test_x86_avx512.cxx b/cmake/test/test_x86_avx512.cxx
index dd673c325..eed07d3f3 100644
--- a/cmake/test/test_x86_avx512.cxx
+++ b/cmake/test/test_x86_avx512.cxx
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <stdlib.h>
 #include <signal.h>
 #include <immintrin.h>
 
diff --git a/cmake/test/test_x86_sse2.cxx b/cmake/test/test_x86_sse2.cxx
index 1bf09eb73..98eb27ea9 100644
--- a/cmake/test/test_x86_sse2.cxx
+++ b/cmake/test/test_x86_sse2.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <emmintrin.h>
 
 void signalHandler(int signum) {
diff --git a/cmake/test/test_x86_sse3.cxx b/cmake/test/test_x86_sse3.cxx
index a09541e61..70a31e3f2 100644
--- a/cmake/test/test_x86_sse3.cxx
+++ b/cmake/test/test_x86_sse3.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <emmintrin.h>
 #include <pmmintrin.h>
 
diff --git a/cmake/test/test_x86_sse41.cxx b/cmake/test/test_x86_sse41.cxx
index 04abc1d92..e08697fb9 100644
--- a/cmake/test/test_x86_sse41.cxx
+++ b/cmake/test/test_x86_sse41.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <emmintrin.h>
 #include <smmintrin.h>
 
diff --git a/cmake/test/test_x86_sse42.cxx b/cmake/test/test_x86_sse42.cxx
index 7f9d81f52..58032a571 100644
--- a/cmake/test/test_x86_sse42.cxx
+++ b/cmake/test/test_x86_sse42.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <nmmintrin.h>
 
 void signalHandler(int signum) {
diff --git a/cmake/test/test_x86_ssse3.cxx b/cmake/test/test_x86_ssse3.cxx
index b29049c2d..01688f4aa 100644
--- a/cmake/test/test_x86_ssse3.cxx
+++ b/cmake/test/test_x86_ssse3.cxx
@@ -1,4 +1,5 @@
 #include <signal.h>
+#include <stdlib.h>
 #include <emmintrin.h>
 #include <tmmintrin.h>
 
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index c9bbd46a6..be4141611 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -7,91 +7,158 @@
 # other viable solution is to use execute_process() during config
 # but make the configuration dirty
 
+# which version/tag/checkout to use
+set(CODEC2_TAG 7a0187da3ffb06fd90c081216b50bab94d02d046)
+set(CM256CC_TAG 19f023d9d6c6f1a2e7dc5bcf466a1424c7918de4)
+set(MBELIB_TAG "debian/1.3.0")
+set(SERIALDV_TAG abd65a0fc2d5339808194862d14119b0cba70424)
+set(DSDCC_TAG 2d60d60f16c1ac778ba518310180f81043befdd0)
+
+
 # For some external project macros
 include(ExternalProject)
 
-# add the build path to cmake
-#list(APPEND CMAKE_PREFIX_PATH "${EXTERNAL_BUILD_LIBRARIES}")
+# default build destination in windows to avoid Release/Debug folder
+if(WIN32)
+  # the build will be output on the same folder of sdrangel
+  set(DEFAULT_OUTPUT_DIRECTORY
+    -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${SDRANGEL_BINARY_BIN_DIR}
+    -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG=${SDRANGEL_BINARY_BIN_DIR}
+    -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=${SDRANGEL_BINARY_BIN_DIR}
+    -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${SDRANGEL_BINARY_LIB_DIR}
+    -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=${SDRANGEL_BINARY_LIB_DIR}
+    -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE=${SDRANGEL_BINARY_LIB_DIR}
+    -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${SDRANGEL_BINARY_LIB_DIR}
+    -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG=${SDRANGEL_BINARY_LIB_DIR}
+    -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=${SDRANGEL_BINARY_LIB_DIR})
+endif()
 
 # macro that create symbolic links
 macro(makeLink src dest target)
-  add_custom_command(TARGET ${target} PRE_BUILD
-    COMMAND ${CMAKE_COMMAND} -E create_symlink ${src} ${dest} DEPENDS  ${dest} COMMENT "mklink ${src} -> ${dest}")
+  if(NOT EXISTS ${dest})
+    add_custom_command(TARGET ${target} PRE_BUILD
+      COMMAND ${CMAKE_COMMAND} -E create_symlink ${src} ${dest} DEPENDS ${dest} COMMENT "mklink ${src} -> ${dest}")
+  endif()
+endmacro()
+# macro that copy folder
+macro(makeCopy src dest target)
+  if(NOT EXISTS ${dest})
+    add_custom_command(TARGET ${target} PRE_BUILD
+      COMMAND ${CMAKE_COMMAND} -E copy_directory ${src} ${dest} DEPENDS ${dest} COMMENT "copy ${src} -> ${dest}")
+  endif()
 endmacro()
 
-# needs boost
-ExternalProject_Add(codec2
+# probably build with mingw64 on windows
+if(NOT WIN32)
+  # needs boost
+  ExternalProject_Add(codec2
     GIT_REPOSITORY https://github.com/drowe67/codec2.git
-    GIT_TAG 7a0187da3ffb06fd90c081216b50bab94d02d046
+    GIT_TAG ${CODEC2_TAG}
     PREFIX "${EXTERNAL_BUILD_LIBRARIES}/codec2"
+    CMAKE_ARGS ${DEFAULT_OUTPUT_DIRECTORY}
     INSTALL_COMMAND ""
     TEST_COMMAND ""
-)
-set(CODEC2_FOUND ON CACHE INTERNAL "")
-set(CODEC2_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/codec2/src/codec2/src" CACHE INTERNAL "")
-set(CODEC2_LIBRARIES "${EXTERNAL_BUILD_LIBRARIES}/codec2/src/codec2-build/libcodec2${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
-# some source include "codec2/comp.h" and some without codec2
-makeLink("${EXTERNAL_BUILD_LIBRARIES}/codec2/src/codec2/src" "${EXTERNAL_BUILD_LIBRARIES}/codec2/src/codec2/src/codec2" codec2)
+  )
+  ExternalProject_Get_Property(codec2 source_dir binary_dir)
+  set(CODEC2_FOUND ON CACHE INTERNAL "")
+  set(CODEC2_INCLUDE_DIR "${source_dir}/src" CACHE INTERNAL "")
+  if(WIN32)
+    set(CODEC2_LIBRARIES "${SDRANGEL_BINARY_LIB_DIR}/codec2.lib" CACHE INTERNAL "")
+    makeCopy("${source_dir}/src" "${source_dir}/src/codec2" codec2)
+  else()
+    set(CODEC2_LIBRARIES "${binary_dir}/libcodec2${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+    # some source include "codec2/comp.h" and some without codec2
+    makeLink("${source_dir}/src" "${source_dir}/src/codec2" codec2)
+  endif()
+endif()
 
 # needs boost
 ExternalProject_Add(cm256cc
     GIT_REPOSITORY https://github.com/f4exb/cm256cc.git
-    GIT_TAG v1.0.5
+    GIT_TAG ${CM256CC_TAG}
     PREFIX "${EXTERNAL_BUILD_LIBRARIES}/cm256cc"
+    CMAKE_ARGS -DBUILD_TOOLS=OFF -DBOOST_ROOT="${BOOST_ROOT}" ${DEFAULT_OUTPUT_DIRECTORY}
     INSTALL_COMMAND ""
     TEST_COMMAND ""
 )
+ExternalProject_Get_Property(cm256cc source_dir binary_dir)
 set(CM256CC_FOUND ON CACHE INTERNAL "")
+# we need cm256cc/library.h
 set(CM256CC_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/cm256cc/src" CACHE INTERNAL "")
-set(CM256CC_LIBRARIES "${EXTERNAL_BUILD_LIBRARIES}/cm256cc/src/cm256cc-build/libcm256cc${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+if(WIN32)
+  set(CM256CC_LIBRARIES "${SDRANGEL_BINARY_LIB_DIR}/cm256cc.lib" CACHE INTERNAL "")
+else()
+  set(CM256CC_LIBRARIES "${binary_dir}/libcm256cc${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+endif()
 
+set(USE_MBELIB OFF)
+if(NOT WIN32)
 ExternalProject_Add(mbelib
     GIT_REPOSITORY https://github.com/szechyjs/mbelib.git
-    GIT_TAG "debian/1.3.0"
+    GIT_TAG ${MBELIB_TAG}
     PREFIX "${EXTERNAL_BUILD_LIBRARIES}/mbelib"
+    CMAKE_ARGS -DDISABLE_TEST=ON ${DEFAULT_OUTPUT_DIRECTORY}
     INSTALL_COMMAND ""
     TEST_COMMAND ""
 )
+ExternalProject_Get_Property(mbelib source_dir binary_dir)
+set(USE_MBELIB ON)
 set(DSDCC_DEPENDS mbelib)
 set(LIBMBE_FOUND)
-set(LIBMBE_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/mbelib/src/mbelib")
-set(LIBMBE_LIBRARIES "${EXTERNAL_BUILD_LIBRARIES}/mbelib/src/mbelib-build/libmbe${CMAKE_SHARED_LIBRARY_SUFFIX}")
+set(LIBMBE_INCLUDE_DIR "${source_dir}")
+if(WIN32)
+  set(LIBMBE_LIBRARIES "${SDRANGEL_BINARY_LIB_DIR}/mbe.lib")
+else()
+  set(LIBMBE_LIBRARIES "${binary_dir}/libmbe${CMAKE_SHARED_LIBRARY_SUFFIX}")
+endif()
+endif(NOT WIN32)
 
 if(WIN32 OR LINUX)
     ExternalProject_Add(serialdv
         GIT_REPOSITORY https://github.com/f4exb/serialDV.git
-        GIT_TAG 89c841ce5b24b8b75c329d6330ec216773f002d2
+        GIT_TAG ${SERIALDV_TAG}
         PREFIX "${EXTERNAL_BUILD_LIBRARIES}/serialdv"
+        CMAKE_ARGS -DBUILD_TOOL=OFF ${DEFAULT_OUTPUT_DIRECTORY}
         INSTALL_COMMAND ""
         TEST_COMMAND ""
     )
+    ExternalProject_Get_Property(serialdv source_dir binary_dir)
     set(DSDCC_DEPENDS ${DSDCC_DEPENDS} serialdv)
     set(LIBSERIALDV_FOUND ON CACHE INTERNAL "")
-    set(LIBSERIALDV_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/serialdv/src/serialdv" CACHE INTERNAL "")
-    set(LIBSERIALDV_LIBRARY "${EXTERNAL_BUILD_LIBRARIES}/serialdv/src/serialdv-build/libserialdv${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
-
-    # because sdrbase/dsp/dvserialworker.h use dsp/dvcontroller.h
-    # so we need a link
-    makeLink("${EXTERNAL_BUILD_LIBRARIES}/serialdv/src/serialdv" "${EXTERNAL_BUILD_LIBRARIES}/serialdv/src/serialdv/dsp" serialdv)
+    set(LIBSERIALDV_INCLUDE_DIR "${source_dir}" CACHE INTERNAL "")
+    if(WIN32)
+      set(LIBSERIALDV_LIBRARY "${SDRANGEL_BINARY_LIB_DIR}/serialdv.lib" CACHE INTERNAL "")
+      makeCopy("${source_dir}" "${source_dir}/dsp" serialdv)
+    else()
+      set(LIBSERIALDV_LIBRARY "${binary_dir}/libserialdv${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+      # because sdrbase/dsp/dvserialworker.h use dsp/dvcontroller.h
+      # so we need a link
+      makeLink("${source_dir}" "${source_dir}/dsp" serialdv)
+    endif()
 endif()
 
 ExternalProject_Add(dsdcc
     GIT_REPOSITORY https://github.com/f4exb/dsdcc.git
-    GIT_TAG cee82816bc8982ecb218abbd2baeb5bb5186711b
+    GIT_TAG ${DSDCC_TAG}
     DEPENDS ${DSDCC_DEPENDS}
     PREFIX "${EXTERNAL_BUILD_LIBRARIES}/dsdcc"
-    CMAKE_ARGS "-DUSE_MBELIB=ON -DLIBMBE_INCLUDE_DIR=${LIBMBE_INCLUDE_DIR} -DLIBMBE_LIBRARY=${LIBMBE_LIBRARIES} -DLIBSERIALDV_INCLUDE_DIR=${LIBSERIALDV_INCLUDE_DIR} -DLIBSERIALDV_LIBRARY=${LIBSERIALDV_LIBRARY}"
+    CMAKE_ARGS ${DEFAULT_OUTPUT_DIRECTORY} -DBUILD_TOOL=OFF -DUSE_MBELIB=${USE_MBELIB} -DLIBMBE_INCLUDE_DIR="${LIBMBE_INCLUDE_DIR}" -DLIBMBE_LIBRARY="${LIBMBE_LIBRARIES}" -DLIBSERIALDV_INCLUDE_DIR="${LIBSERIALDV_INCLUDE_DIR}" -DLIBSERIALDV_LIBRARY="${LIBSERIALDV_LIBRARY}"
     INSTALL_COMMAND ""
     TEST_COMMAND ""
 )
+ExternalProject_Get_Property(dsdcc source_dir binary_dir)
 set(LIBDSDCC_FOUND ON CACHE INTERNAL "")
 set(LIBDSDCC_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/dsdcc/src" CACHE INTERNAL "")
-set(LIBDSDCC_LIBRARIES "${EXTERNAL_BUILD_LIBRARIES}/dsdcc/src/dsdcc-build/libdsdcc${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+if(WIN32)
+  set(LIBDSDCC_LIBRARIES "${SDRANGEL_BINARY_LIB_DIR}/dsdcc.lib" CACHE INTERNAL "")
+else()
+  set(LIBDSDCC_LIBRARIES "${binary_dir}/libdsdcc${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE INTERNAL "")
+endif()
 
 # already on the respository
 # TODO decide what to do
 if(OFF)
-# needs pkgconfig, libusb, autoconf, automake and autolib
+# needs pkgconfig, libusb, autoconf, automake and libtool
 ExternalProject_Add(perseus
     GIT_REPOSITORY https://github.com/f4exb/libperseus-sdr.git
     GIT_TAG afefa23e3140ac79d845acb68cf0beeb86d09028
diff --git a/external/windows b/external/windows
index e09fc96d9..efa84ff29 160000
--- a/external/windows
+++ b/external/windows
@@ -1 +1 @@
-Subproject commit e09fc96d9998207336dfcb42122c046bafd0bdee
+Subproject commit efa84ff291820aa476e9f67286e0162ecab9f806
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 043e23a8e..84bac4c75 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -7,11 +7,29 @@ include_directories(
 )
 
 if (NOT SERVER_MODE)
-    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR})
-    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR})
+    if(WIN32)
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PLUGINS_RUNTIME_DIR}")
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_RUNTIME_DIR}")
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_RUNTIME_DIR}")
+    endif()
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PLUGINS_DIR}")
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_DIR}")
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINS_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_DIR}")
 else()
-    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PLUGINSSRV_DIR})
-    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINSSRV_DIR})
+    if(WIN32)
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
+        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
+    endif()
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_DIR}")
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_DIR}")
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_DIR}")
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_DIR}")
 endif()
 
 add_subdirectory(channelrx)
diff --git a/plugins/channelrx/CMakeLists.txt b/plugins/channelrx/CMakeLists.txt
index bdf35816f..60f72906d 100644
--- a/plugins/channelrx/CMakeLists.txt
+++ b/plugins/channelrx/CMakeLists.txt
@@ -33,6 +33,9 @@ if(NOT SERVER_MODE)
     # TODO use libavcodec/version.h
     find_package(FFmpeg)
     if (FFMPEG_FOUND)
+      if(WIN32)
+        add_subdirectory(demoddatv)
+      else()
         # You can only get FFmpeg version from the command line
         EXECUTE_PROCESS(COMMAND ffmpeg -version COMMAND grep ffmpeg COMMAND cut -d\  -f3 COMMAND tr -d '\n' OUTPUT_VARIABLE FFMPEG_VERSION)
         message(STATUS "FFmpeg version ${FFMPEG_VERSION} found")
@@ -42,5 +45,6 @@ if(NOT SERVER_MODE)
         else()
             message(STATUS "FFmpeg too old to compile demoddatv; needs at least ffmpeg 3.1")
         endif()
+      endif()
     endif()
 endif()
diff --git a/plugins/samplesink/localoutput/ccc.txt b/plugins/samplesink/localoutput/ccc.txt
deleted file mode 100644
index 0059880a8..000000000
--- a/plugins/samplesink/localoutput/ccc.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-project(localoutput)
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-
-set(localoutput_SOURCES
-	localoutputgui.cpp
-	localoutput.cpp
-	localoutputplugin.cpp
-	localoutputsettings.cpp
-)
-
-set(localoutput_HEADERS
-	localoutputgui.h
-	localoutput.h
-	localoutputplugin.h
-	localoutputsettings.h
-)
-
-set(localoutput_FORMS
-	localoutputgui.ui
-)
-
-include_directories(
-    .
-    ${CMAKE_CURRENT_BINARY_DIR}
-    ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
-)
-
-add_definitions(${QT_DEFINITIONS})
-add_definitions(-DQT_PLUGIN)
-add_definitions(-DQT_SHARED)
-
-qt5_wrap_ui(localoutput_FORMS_HEADERS ${localoutput_FORMS})
-
-add_library(outputlocal SHARED
-	${localoutput_SOURCES}
-	${localoutput_HEADERS_MOC}
-	${localoutput_FORMS_HEADERS}
-)
-
-target_link_libraries(outputlocal
-    ${QT_LIBRARIES}
-    sdrbase
-    sdrgui
-    swagger
-)
-
-target_link_libraries(outputlocal Qt5::Core Qt5::Widgets)
-
-install(TARGETS outputlocal DESTINATION lib/plugins/samplesink)
diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp
index 57591cfec..63ebe5a08 100644
--- a/sdrbase/plugin/pluginmanager.cpp
+++ b/sdrbase/plugin/pluginmanager.cpp
@@ -75,6 +75,8 @@ void PluginManager::loadPluginsPart(const QString& pluginsSubDir)
 #ifdef __APPLE__
     // on SDRAngel.app
     PluginsPath << applicationDirPath + "/../Resources/lib/" + pluginsSubDir;
+#elif defined(_WIN32) || defined(WIN32)
+    PluginsPath << applicationDirPath + "/" + pluginsSubDir;
 #endif
 
     // NOTE: exit on the first folder found
diff --git a/sdrsrv/CMakeLists.txt b/sdrsrv/CMakeLists.txt
index 4be6c8fa9..47da06ad2 100644
--- a/sdrsrv/CMakeLists.txt
+++ b/sdrsrv/CMakeLists.txt
@@ -12,21 +12,7 @@ set(sdrsrv_HEADERS
     webapi/webapiadaptersrv.h
 )
 
-set(sdrsrv_SOURCES
-    ${sdrsrv_SOURCES}
-    ${sdrsrv_HEADERS}
-)
-
-add_definitions(${QT_DEFINITIONS})
-add_definitions(-DQT_SHARED)
-
-add_library(sdrsrv SHARED
-    ${sdrsrv_SOURCES}
-    ${sdrsrv_HEADERS_MOC}
-)
-
 include_directories(
-    .
     ${CMAKE_SOURCE_DIR}/exports
     ${CMAKE_SOURCE_DIR}/sdrbase
     ${CMAKE_SOURCE_DIR}/logging
@@ -35,15 +21,16 @@ include_directories(
     ${OPENGL_INCLUDE_DIR}
 )
 
+add_library(sdrsrv SHARED
+    ${sdrsrv_SOURCES}
+)
+
 target_link_libraries(sdrsrv
-    ${QT_LIBRARIES}
+    Qt5::Core
+    Qt5::Multimedia
     sdrbase
     logging
 )
 
-target_compile_features(sdrsrv PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0
-
-target_link_libraries(sdrsrv Qt5::Core Qt5::Multimedia)
-
 install(TARGETS sdrsrv DESTINATION ${INSTALL_LIB_DIR})