From 9d2a4b2ef08beda734514a820e3061ee810ac8b2 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Mon, 5 Jun 2017 14:52:29 -0700 Subject: [PATCH] [Mingw64] Set command variables correctly for Guile2 compilation. Mingw-w64 linker uses $PATH instead of $LD_LIBRARY_PATH for finding shared libraries. Both the linker and Guile itself need MSys/Unix style paths with the drive letter as a top-level directory, forward slashes, and separated with ':' while CMake wants Windows-style paths separated with ';'. --- src/cmake_modules/GncAddSchemeTargets.cmake | 163 +++++++++++++------- src/cmake_modules/GncAddTest.cmake | 31 +++- 2 files changed, 131 insertions(+), 63 deletions(-) diff --git a/src/cmake_modules/GncAddSchemeTargets.cmake b/src/cmake_modules/GncAddSchemeTargets.cmake index 052849a60c..def3ac3a17 100644 --- a/src/cmake_modules/GncAddSchemeTargets.cmake +++ b/src/cmake_modules/GncAddSchemeTargets.cmake @@ -1,33 +1,76 @@ +# GncAddSchemeTargets.cmake Define a command to compile Scheme programs with Guile # Copyright (c) 2015, Rob Gowin +# Copyright 2017 John Ralls +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, contact: +# Free Software Foundation Voice: +1-617-542-5942 +# 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 +# Boston, MA 02110-1301, USA gnu@gnu.org -MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES _GUILE_LOAD_DIRS _GUILE_LIBRARY_DIRS _GUILE_DEPENDS_IN MAKE_LINKS_IN) - SET(__DEBUG FALSE) +#Guile and ltdl require MSYS paths on MinGW-w64; this function transforms them. +FUNCTION(MAKE_UNIX_PATH PATH) + STRING(REGEX REPLACE "^([A-Za-z]):" "/\\1" newpath ${${PATH}}) + string(REGEX REPLACE "\\\\" "/" newpath ${newpath}) + SET(${PATH} ${newpath} PARENT_SCOPE) +ENDFUNCTION() + +#PATH variables in the environment are separated by colons, but CMake lists are separated by semicolons. This function transforms the separators. +FUNCTION(MAKE_UNIX_PATH_LIST PATH) + STRING(REPLACE ";" ":" newpath "${${PATH}}") + SET(${PATH} ${newpath} PARENT_SCOPE) +ENDFUNCTION() + +FUNCTION(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR + _GUILE_MODULES _GUILE_LOAD_DIRS + _GUILE_LIBRARY_DIRS _GUILE_DEPENDS + MAKE_LINKS) + SET(__DEBUG TRUE) IF (__DEBUG) MESSAGE("Parameters to COMPILE_SCHEME for target ${_TARGET}") MESSAGE(" SOURCE_FILES: ${_SOURCE_FILES}") MESSAGE(" GUILE_MODULES: ${_GUILE_MODULES}") MESSAGE(" GUILE_LOAD_DIRS: ${_GUILE_LOAD_DIRS}") MESSAGE(" GUILE_LIBRARY_DIRS: ${_GUILE_LIBRARY_DIRS}") - MESSAGE(" GUILE_DEPENDS_IN: ${_GUILE_DEPENDS_IN}") + MESSAGE(" GUILE_DEPENDS: ${_GUILE_DEPENDS}") + MESSAGE(" DIRECTORIES: ${BINDIR_BUILD}, ${LIBDIR_BUILD}, ${DATADIR_BUILD}") ENDIF(__DEBUG) SET(_CMD "create_symlink") IF(WIN32) SET(_CMD "copy") ENDIF(WIN32) - SET(MAKE_LINKS ${MAKE_LINKS_IN}) - SET(_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${_OUTPUT_DIR_IN}) - SET(_OUTPUT_DIR ${DATADIR_BUILD}/gnucash/scm/${_OUTPUT_DIR_IN}) - FILE(MAKE_DIRECTORY ${_OUTPUT_DIR}) + SET(current_srcdir ${CMAKE_CURRENT_SOURCE_DIR}) + SET(current_bindir ${CMAKE_CURRENT_BINARY_DIR}) + SET(build_bindir ${BINDIR_BUILD}) + SET(build_libdir ${LIBDIR_BUILD}) + SET(build_datadir ${DATADIR_BUILD}) + IF(MINGW64) + MAKE_UNIX_PATH(build_bindir) + MAKE_UNIX_PATH(build_libdir) + MAKE_UNIX_PATH(build_datadir) + MAKE_UNIX_PATH(current_bindir) + MAKE_UNIX_PATH(current_srcdir) + MAKE_UNIX_PATH(CMAKE_BINARY_DIR) + MAKE_UNIX_PATH(CMAKE_SOURCE_DIR) + ENDIF(MINGW64) + # For guile 1, we simple link (or copy, for Windows) each source file to the dest directory IF(HAVE_GUILE1 OR MAKE_LINKS) + SET(_LINK_DIR ${DATADIR_BUILD}/gnucash/scm/${_OUTPUT_DIR}) + FILE(MAKE_DIRECTORY ${_LINK_DIR}) SET(_SCHEME_LINKS "") FOREACH(scheme_file ${_SOURCE_FILES}) - SET(_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${scheme_file}) + SET(_SOURCE_FILE ${current_srcdir}/${scheme_file}) IF(IS_ABSOLUTE ${scheme_file}) SET(_SOURCE_FILE ${scheme_file}) ENDIF() GET_FILENAME_COMPONENT(name ${scheme_file} NAME) - SET(_OUTPUT_FILE ${_OUTPUT_DIR}/${name}) + SET(_OUTPUT_FILE ${_LINK_DIR}/${name}) IF(NOT EXISTS ${_OUTPUT_FILE}) LIST(APPEND _SCHEME_LINKS ${_OUTPUT_FILE}) ADD_CUSTOM_COMMAND( @@ -45,56 +88,31 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES IF(HAVE_GUILE2) # Construct the guile source and compiled load paths - SET(_GUILE_LOAD_PATH "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};${CMAKE_BINARY_DIR}/src/scm") # to pick up generated build-config.scm - SET(_GUILE_LOAD_COMPILED_PATH "${CMAKE_CURRENT_BINARY_DIR}") + + SET(_GUILE_LOAD_PATH "${current_srcdir}" + "${current_bindir}" "${CMAKE_BINARY_DIR}/src/scm") # to pick up generated build-config.scm + SET(_GUILE_LOAD_COMPILED_PATH "${current_bindir}") FOREACH (load_item ${_GUILE_LOAD_DIRS}) - LIST(APPEND _GUILE_LOAD_PATH ${CMAKE_SOURCE_DIR}/${load_item}) - LIST(APPEND _GUILE_LOAD_COMPILED_PATH ${CMAKE_BINARY_DIR}/${load_item}) + LIST(APPEND _GUILE_LOAD_PATH "${CMAKE_SOURCE_DIR}/${load_item}") ENDFOREACH(load_item) - # Construct the LD_LIBRARY_PATH - SET(_GUILE_LD_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}) - FOREACH(ld_item ${_GUILE_LIBRARY_DIRS}) - LIST(APPEND _GUILE_LD_LIBRARY_PATH ${CMAKE_BINARY_DIR}/${ld_item}/${CMAKE_BUILD_TYPE}) - ENDFOREACH(ld_item) - - # And then the module path - SET(_GNC_MODULE_PATH "") - FOREACH(module_item ${_GUILE_MODULES}) - LIST(APPEND _GNC_MODULE_PATH ${CMAKE_BINARY_DIR}/${module_item}/${CMAKE_BUILD_TYPE}) - ENDFOREACH(module_item) - - # In CMake lists are text strings where the items are separated by semicolons ("a;b;c;d" for example). - # Replace the semis with colons to construct the path environment variables - STRING(REPLACE ";" ":" _GUILE_LOAD_PATH "${_GUILE_LOAD_PATH}") - STRING(REPLACE ";" ":" _GUILE_LOAD_COMPILED_PATH "${_GUILE_LOAD_COMPILED_PATH}") - STRING(REPLACE ";" ":" _GUILE_MODULES "{_GUILE_MODULES}") - STRING(REPLACE ";" ":" _GUILE_LD_LIBRARY_PATH "${_GUILE_LD_LIBRARY_PATH}") - STRING(REPLACE ";" ":" _GNC_MODULE_PATH "${_GNC_MODULE_PATH}") - SET(_GUILE_CACHE_DIR ${LIBDIR_BUILD}/gnucash/scm/ccache/2.0) - SET(_GUILE_LOAD_PATH "${CMAKE_CURRENT_SOURCE_DIR}:${DATADIR_BUILD}/gnucash/scm") - SET(_GUILE_LOAD_COMPILED_PATH ${_GUILE_CACHE_DIR}) -# SET(_GNC_MODULE_PATH "${LIBDIR_BUILD}/${CMAKE_BUILD_TYPE}:${LIBDIR_BUILD}/gnucash/${CMAKE_BUILD_TYPE}") - SET(_GNC_MODULE_PATH "") - SET(_GUILE_LD_LIBRARY_PATH ${_GNC_MODULE_PATH}) - IF (__DEBUG) - MESSAGE(" ") - MESSAGE(" GUILE_LOAD_PATH: ${_GUILE_LOAD_PATH}") - MESSAGE(" GUILE_LOAD_COMPILED_PATH: ${_GUILE_LOAD_COMPILED_PATH}") - MESSAGE(" GUILE_LD_LIBRARY_PATH: ${_GUILE_LD_LIBRARY_PATH}") - MESSAGE(" GNC_MODULE_PATH: ${_GNC_MODULE_PATH}") - ENDIF(__DEBUG) + SET(_GUILE_LOAD_PATH "${current_srcdir}") + IF (MAKE_LINKS) + LIST(APPEND _GUILE_LOAD_PATH "${build_datadir}/gnucash/scm") + ENDIF() + SET(_GUILE_LOAD_COMPILED_PATH ${build_libdir}/gnucash/scm/ccache/2.0) + SET(_TARGET_FILES "") FOREACH(source_file ${_SOURCE_FILES}) - SET(guile_depends ${_GUILE_DEPENDS_IN}) + SET(guile_depends ${_GUILE_DEPENDS}) GET_FILENAME_COMPONENT(basename ${source_file} NAME_WE) SET(output_file ${basename}.go) - SET(_TMP_OUTPUT_DIR_IN ${_OUTPUT_DIR_IN}) - IF (_TMP_OUTPUT_DIR_IN) - SET(output_file ${_OUTPUT_DIR_IN}/${basename}.go) + SET(_TMP_OUTPUT_DIR ${_OUTPUT_DIR}) + IF (_TMP_OUTPUT_DIR) + SET(output_file ${_OUTPUT_DIR}/${basename}.go) ENDIF() SET(output_file ${_GUILE_CACHE_DIR}/${output_file}) LIST(APPEND _TARGET_FILES ${output_file}) @@ -110,18 +128,46 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES IF (${CMAKE_VERSION} VERSION_GREATER 3.1) SET(CMAKE_COMMAND_TMP ${CMAKE_COMMAND} -E env) ENDIF() + IF (MINGW64) + set(fpath "") + foreach(dir $ENV{PATH}) + MAKE_UNIX_PATH(dir) + set(fpath "${fpath}${dir}:") + endforeach(dir) + SET(LIBRARY_PATH "PATH=\"${build_bindir}:${fpath}\"") + ELSE (MINGW64) + SET (LIBRARY_PATH "LD_LIBRARY_PATH=${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}") + ENDIF (MINGW64) + IF (APPLE) + SET (LIBRARY_PATH "DYLD_LIBRARY_PATH=${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}") + ENDIF (APPLE) + SET(_GNC_MODULE_PATH "") + IF(MINGW64) + SET(_GNC_MODULE_PATH "${build_bindir}") + ELSE(MINGW64) + SET(_GNC_MODULE_PATH "${LIBDIR_BUILD}" "${LIBDIR_BUILD}/gnucash" "${GNC_MODULE_PATH}") + ENDIF(MINGW64) + MAKE_UNIX_PATH_LIST(_GUILE_LOAD_PATH) + MAKE_UNIX_PATH_LIST(_GUILE_LOAD_COMPILED_PATH) + MAKE_UNIX_PATH_LIST(_GUILE_MODULES) + MAKE_UNIX_PATH_LIST(_GUILE_LD_LIBRARY_PATH) + MAKE_UNIX_PATH_LIST(_GNC_MODULE_PATH) + IF (__DEBUG) + MESSAGE(" ") + MESSAGE(" LIBRARY_PATH: ${LIBRARY_PATH}") + MESSAGE(" GUILE_LOAD_PATH: ${_GUILE_LOAD_PATH}") + MESSAGE(" GUILE_LOAD_COMPILED_PATH: ${_GUILE_LOAD_COMPILED_PATH}") + MESSAGE(" GNC_MODULE_PATH: ${_GNC_MODULE_PATH}") + ENDIF(__DEBUG) ADD_CUSTOM_COMMAND( OUTPUT ${output_file} COMMAND ${CMAKE_COMMAND_TMP} - GNC_UNINSTALLED=${_GNC_UNINSTALLED} + ${LIBRARY_PATH} + GNC_UNINSTALLED=YES GNC_BUILDDIR=${CMAKE_BINARY_DIR} - #DYLD_FALLBACK_LIBRARY_PATH=${Boost_LIBRARY_DIRS} # this is hack for OS X - LD_LIBRARY_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}" - DYLD_LIBRARY_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}" GUILE_LOAD_PATH=${_GUILE_LOAD_PATH} GUILE_LOAD_COMPILED_PATH=${_GUILE_LOAD_COMPILED_PATH} - #GNC_MODULE_PATH=${_GNC_MODULE_PATH} - GNC_MODULE_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${GNC_MODULE_PATH}" + GNC_MODULE_PATH=${_GNC_MODULE_PATH} ${GUILE_EXECUTABLE} -e '\(@@ \(guild\) main\)' -s ${GUILD_EXECUTABLE} compile -o ${output_file} ${source_file_abs_path} DEPENDS ${guile_depends} MAIN_DEPENDENCY ${source_file_abs_path} @@ -131,8 +177,7 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES MESSAGE("TARGET_FILES are ${_TARGET_FILES}") ENDIF(__DEBUG) ADD_CUSTOM_TARGET(${_TARGET} ALL DEPENDS ${_TARGET_FILES}) - INSTALL(FILES ${_TARGET_FILES} DESTINATION ${SCHEME_INSTALLED_CACHE_DIR}/${_OUTPUT_DIR_IN}) - + INSTALL(FILES ${_TARGET_FILES} DESTINATION ${SCHEME_INSTALLED_CACHE_DIR}/${_OUTPUT_DIR}) ENDIF(HAVE_GUILE2) - INSTALL(FILES ${_SOURCE_FILES} DESTINATION ${SCHEME_INSTALLED_SOURCE_DIR}/${_OUTPUT_DIR_IN}) -ENDMACRO(GNC_ADD_SCHEME_TARGETS) + INSTALL(FILES ${_SOURCE_FILES} DESTINATION ${SCHEME_INSTALLED_SOURCE_DIR}/${_OUTPUT_DIR}) +ENDFUNCTION(GNC_ADD_SCHEME_TARGETS) diff --git a/src/cmake_modules/GncAddTest.cmake b/src/cmake_modules/GncAddTest.cmake index 9ccf2b2d48..b76fd8e447 100644 --- a/src/cmake_modules/GncAddTest.cmake +++ b/src/cmake_modules/GncAddTest.cmake @@ -9,13 +9,29 @@ FUNCTION(GET_GUILE_ENV) LIST(APPEND env "GNC_UNINSTALLED=yes") LIST(APPEND env "GNC_BUILDDIR=${CMAKE_BINARY_DIR}") LIST(APPEND env "GUILE_WARN_DEPRECATED=no") - LIST(APPEND env "GNC_MODULE_PATH=${_GNC_MODULE_PATH}") IF (APPLE) LIST(APPEND env "DYLD_LIBRARY_PATH=${_GNC_MODULE_PATH}") ENDIF() IF (UNIX) LIST(APPEND env LD_LIBRARY_PATH=${_GNC_MODULE_PATH}) ENDIF() + IF (MINGW64) + set(fpath "") + set(path $ENV{PATH}) + list(INSERT path 0 ${CMAKE_BINARY_DIR}/bin) + foreach(dir ${path}) + string(REGEX REPLACE "^([A-Za-z]):" "/\\1" dir ${dir}) + string(REGEX REPLACE "\\\\" "/" dir ${dir}) + set(fpath "${fpath}${dir}:") + endforeach(dir) + LIST(APPEND env "PATH=${fpath}") + set(compiled_path "${CMAKE_BINARY_DIR}/lib/gnucash/scm/ccache/2.0") + string(REGEX REPLACE "^([A-Za-z]):" "/\\1" compiled_path ${compiled_path}) + LIST(APPEND env GUILE_LOAD_COMPILED_PATH=${compiled_path}) + ENDIF(MINGW64) + LIST(APPEND env "GNC_MODULE_PATH=${_GNC_MODULE_PATH}") + LIST(APPEND env "GUILE=${GUILE_EXECUTABLE}") + IF (NOT WIN32) LIST(APPEND env "GUILE_LOAD_COMPILED_PATH=${CMAKE_BINARY_DIR}/lib/gnucash/scm/ccache/2.0") ENDIF() @@ -27,13 +43,20 @@ FUNCTION(GET_GUILE_ENV) LIST(APPEND guile_load_paths ${CMAKE_BINARY_DIR}/share/gnucash/scm) ENDIF() SET(guile_load_path "${guile_load_paths}") - IF (WIN32) + IF (MINGW64) + set(new_path "") + FOREACH(load_item ${guile_load_path}) + string(REGEX REPLACE "^([A-Za-z]):" "/\\1" load_item ${load_item}) + list(APPEND new_path ${load_item}) + ENDFOREACH(load_item) + set(guile_load_path ${new_path}) + ENDIF (MINGW64) + IF (WIN32 AND NOT MINGW64) STRING(REPLACE ";" "\\\\;" GUILE_LOAD_PATH "${guile_load_path}") ELSE() STRING(REPLACE ";" ":" GUILE_LOAD_PATH "${guile_load_path}") ENDIF() - LIST(APPEND env "GUILE_LOAD_PATH=${GUILE_LOAD_PATH}") - LIST(APPEND env "GUILE=${GUILE_EXECUTABLE}") + LIST(APPEND env GUILE_LOAD_PATH=${GUILE_LOAD_PATH}) SET(GUILE_ENV ${env} PARENT_SCOPE) ENDFUNCTION()