CMake: Rework Haskell package detection, use ghc-pkg to detect packages
authorWuzzy <Wuzzy2@mail.ru>
Wed, 28 Mar 2018 15:14:20 +0200
changeset 13296 31615a2e0db1
parent 13295 a3b07219a091
child 13297 e9caada3aac1
CMake: Rework Haskell package detection, use ghc-pkg to detect packages
cmake_modules/CheckHaskellModuleExists.cmake
cmake_modules/CheckHaskellPackageExists.cmake
cmake_modules/FindGHC.cmake
gameServer/CMakeLists.txt
--- a/cmake_modules/CheckHaskellModuleExists.cmake	Wed Mar 28 14:06:34 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-# Based on CheckLibraryExists.cmake from CMake
-#=============================================================================
-# Copyright 2002-2009 Kitware, Inc.
-#
-# Distributed under the OSI-approved BSD License
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-
-macro(CHECK_HASKELL_MODULE_EXISTS MODULE FUNCTION PARAMCOUNT LIBRARY)
-  set(VARIABLE "HS_MODULE_${LIBRARY}_${FUNCTION}")
-  if(${VARIABLE} MATCHES ^${VARIABLE}$)
-    message(STATUS "Looking for ${FUNCTION} in ${MODULE}")
-
-    set(PARAMETERS "")
-
-    if(PARAMCOUNT GREATER 0)
-        foreach(__TRASH__ RANGE 1 ${PARAMCOUNT})
-            set(PARAMETERS "${PARAMETERS} undefined")
-        endforeach()
-    endif()
-
-    #set(PARAMETERS "")
-
-    execute_process(COMMAND ${GHC_EXECUTABLE}
-                    "-DMODULE=${MODULE}"
-                    "-DFUNCTION=${FUNCTION}"
-                    "-DPARAMETERS=${PARAMETERS}"
-                    -hide-all-packages
-                    -package ${LIBRARY}
-                    -package base
-                    -cpp
-                    -c "${CMAKE_MODULE_PATH}/checkModule.hs"
-                    RESULT_VARIABLE COMMAND_RESULT
-                    ERROR_VARIABLE BUILD_ERROR
-                    OUTPUT_STRIP_TRAILING_WHITESPACE
-                    )
-    if(${COMMAND_RESULT} EQUAL 0)
-      message(STATUS "Looking for ${FUNCTION} in ${MODULE} - found")
-      set(${VARIABLE} 1 CACHE INTERNAL "Have module ${MODULE}")
-      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
-        "Determining if the function ${FUNCTION} exists in the ${MODULE} passed\n\n")
-    else()
-      message(STATUS "Looking for ${FUNCTION} in ${MODULE} - not found")
-      set(${VARIABLE} "" CACHE INTERNAL "Have module ${MODULE}")
-      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
-        "Determining if the function ${FUNCTION} exists in the ${MODULE} "
-        "failed with the following output:\n"
-        "${BUILD_ERROR}\n\n")
-      message(FATAL_ERROR "Haskell library '${LIBRARY}' required")
-    endif()
-  endif()
-endmacro()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/CheckHaskellPackageExists.cmake	Wed Mar 28 15:14:20 2018 +0200
@@ -0,0 +1,47 @@
+# Checks if a given Haskell package exists (using ghc-pkg)
+# and fails if it's missing.
+# Loosely based on CheckLibraryExists.cmake from CMake.
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+macro(CHECK_HASKELL_PACKAGE_EXISTS PACKAGE MODULE FUNCTION PARAMCOUNT)
+# NOTE: MODULE, FUNCTION and PARAMCOUNT are curretly ignored.
+# TODO: Either implement these or drop?
+
+  set(VARIABLE "HS_PACKAGE_${PACKAGE}")
+  if(NOT (${VARIABLE} EQUAL "1"))
+    message(STATUS "Looking for Haskell package ${PACKAGE} ...")
+
+    execute_process(COMMAND ${GHC_PKG_EXECUTABLE}
+                    "latest"
+                    ${PACKAGE}
+                    "--simple-output"
+                    RESULT_VARIABLE COMMAND_RESULT
+                    ERROR_VARIABLE BUILD_ERROR
+                    OUTPUT_STRIP_TRAILING_WHITESPACE
+                    OUTPUT_QUIET
+                    )
+
+    if(${COMMAND_RESULT} EQUAL 0)
+      message(STATUS "Looking for Haskell package ${PACKAGE} - found")
+      set(${VARIABLE} "1" CACHE INTERNAL "Have package ${PACKAGE}")
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Determining if the Haskell package ${PACKAGE} exists has passed\n\n")
+    else()
+      message(STATUS "Looking for Haskell package ${PACKAGE} - not found")
+      set(${VARIABLE} "0" CACHE INTERNAL "Have package ${PACKAGE}")
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Determining if the Haskell package ${PACKAGE} "
+        "exists failed with the following output:\n"
+        "${BUILD_ERROR}\n\n")
+      message(FATAL_ERROR "Haskell package '${PACKAGE}' required")
+    endif()
+  endif()
+endmacro()
--- a/cmake_modules/FindGHC.cmake	Wed Mar 28 14:06:34 2018 +0200
+++ b/cmake_modules/FindGHC.cmake	Wed Mar 28 15:14:20 2018 +0200
@@ -1,9 +1,10 @@
 # - Try to find the Glasgow Haskell Compiler executable
 # Once done this will define
 #
-#  GHC_FOUND       - system has GHC
-#  GHC_VERSION     - GHC version
-#  GHC_EXECUTABLE  - GHC executable
+#  GHC_VERSION        - GHC version
+#  GHC_EXECUTABLE     - GHC executable
+#  GHC_PKG_VERSION    - ghc-pkg version
+#  GHC_PKG_EXECUTABLE - ghc-pkg executable
 #
 # Copyright (c) 2013, Vittorio Giovara <vittorio.giovara@gmail.com>
 #
@@ -16,6 +17,11 @@
     PATHS /opt/local/bin /usr/local/bin /usr/bin
     )
 
+find_program(GHC_PKG_EXECUTABLE
+    NAMES ghc-pkg
+    PATHS /opt/local/bin /usr/local/bin /usr/bin
+    )
+
 if (GHC_EXECUTABLE)
     # check ghc version
     execute_process(COMMAND ${GHC_EXECUTABLE} -V
@@ -32,6 +38,22 @@
     endif()
 endif()
 
+if (GHC_PKG_EXECUTABLE)
+    # check ghc-pkg version
+    execute_process(COMMAND ${GHC_PKG_EXECUTABLE} -V
+                    OUTPUT_VARIABLE GHC_PKG_VERSION_OUTPUT
+                    ERROR_VARIABLE GHC_PKG_VERSION_ERROR
+                    RESULT_VARIABLE GHC_PKG_VERSION_RESULT
+                    OUTPUT_STRIP_TRAILING_WHITESPACE
+                    )
+
+    if(${GHC_PKG_VERSION_RESULT} EQUAL 0)
+        string(REGEX MATCH "([0-9]+)" GHC_PKG_VERSION ${GHC_PKG_VERSION_OUTPUT})
+    else()
+        message(SEND_ERROR "Command \"${GHC_PKG_EXECUTABLE} -V\" failed with output: ${GHC_PKG_VERSION_ERROR}")
+    endif()
+endif()
+
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(GHC DEFAULT_MSG GHC_EXECUTABLE GHC_VERSION)
 mark_as_advanced(GHC_VERSION)
--- a/gameServer/CMakeLists.txt	Wed Mar 28 14:06:34 2018 +0200
+++ b/gameServer/CMakeLists.txt	Wed Mar 28 15:14:20 2018 +0200
@@ -3,27 +3,25 @@
 
 find_package_or_disable(GHC NOSERVER)
 
-include(${CMAKE_MODULE_PATH}/CheckHaskellModuleExists.cmake)
+include(${CMAKE_MODULE_PATH}/CheckHaskellPackageExists.cmake)
 
-check_haskell_module_exists("Control.Exception" mask 1 base)
-check_haskell_module_exists("Data.Map" size 1 containers)
-check_haskell_module_exists("Data.Vector" length 1 vector)
-check_haskell_module_exists("Data.ByteString" pack 1 bytestring)
-check_haskell_module_exists("Network.BSD" getHostName 0 network)
-check_haskell_module_exists("Data.Time" getCurrentTime 0 time)
-check_haskell_module_exists("Control.Monad.State" fix 1 mtl)
-check_haskell_module_exists("Codec.Binary.Base64" encode 1 sandi)
-check_haskell_module_exists("System.Log.Logger" warningM 1 hslogger)
-check_haskell_module_exists("System.Process" createProcess 3 process)
-check_haskell_module_exists("Data.ByteString.Lazy.UTF8" decode 1 utf8-string)
-check_haskell_module_exists("Data.Digest.Pure.SHA" sha1 1 SHA)
-check_haskell_module_exists("System.Entropy" openHandle 0 entropy)
-check_haskell_module_exists("Codec.Compression.Zlib" decompress 1 zlib)
-check_haskell_module_exists("System.Random" getStdGen 0 random)
-check_haskell_module_exists("Text.Regex.TDFA.ByteString" execute 2 regex-tdfa)
-
-# this one needs type signatures to work
-# check_haskell_module_exists("Control.DeepSeq" deepseq 2 deepseq)
+check_haskell_package_exists(base "Control.Exception" mask 1)
+check_haskell_package_exists(containers "Data.Map" size 1)
+check_haskell_package_exists(vector "Data.Vector" length 1)
+check_haskell_package_exists(bytestring "Data.ByteString" pack 1)
+check_haskell_package_exists(network "Network.BSD" getHostName 0)
+check_haskell_package_exists(time "Data.Time" getCurrentTime 0)
+check_haskell_package_exists(mtl "Control.Monad.State" fix 1)
+check_haskell_package_exists(sandi "Codec.Binary.Base64" encode 1)
+check_haskell_package_exists(hslogger "System.Log.Logger" warningM 1)
+check_haskell_package_exists(process "System.Process" createProcess 3)
+check_haskell_package_exists(utf8-string "Data.ByteString.Lazy.UTF8" decode 1)
+check_haskell_package_exists(SHA "Data.Digest.Pure.SHA" sha1 1)
+check_haskell_package_exists(entropy "System.Entropy" openHandle 0)
+check_haskell_package_exists(zlib "Codec.Compression.Zlib" decompress 1)
+check_haskell_package_exists(random "System.Random" getStdGen 0)
+check_haskell_package_exists(regex-tdfa "Text.Regex.TDFA.ByteString" execute 2)
+check_haskell_package_exists(deepseq "Control.DeepSeq" deepseq 2)