From 9eb6ab384ec1d5ae7140071935e834f14ff475a1 Mon Sep 17 00:00:00 2001 From: Mark Laws Date: Sat, 20 Jan 2018 10:16:48 +0900 Subject: [PATCH 1/2] Fixes for GHC 8.x, archive loading, -dynamic, and file generation --- config.h.in | 3 + configure | 312 ++++++++++++++++-------------- plugins.cabal | 1 + src/System/Eval/Haskell.hs | 2 +- src/System/Plugins/Consts.hs | 4 +- src/System/Plugins/Env.hs | 67 +++++-- src/System/Plugins/Load.hs | 46 +++-- src/System/Plugins/Utils.hs | 159 ++++++++++++--- testsuite/build.mk | 4 +- testsuite/dynload/io/TestIO.hs | 5 +- testsuite/dynload/io/api/API.hs | 7 +- testsuite/dynload/io/prog/Main.hs | 15 +- testsuite/load/plain/Makefile | 6 + testsuite/load/plain/TestIO.hs | 11 ++ testsuite/load/plain/api/API.hs | 10 + testsuite/load/plain/prog/Main.hs | 22 +++ 16 files changed, 458 insertions(+), 216 deletions(-) mode change 100644 => 100755 configure create mode 100644 testsuite/load/plain/Makefile create mode 100644 testsuite/load/plain/TestIO.hs create mode 100644 testsuite/load/plain/api/API.hs create mode 100644 testsuite/load/plain/prog/Main.hs diff --git a/config.h.in b/config.h.in index b96798b..fff7860 100644 --- a/config.h.in +++ b/config.h.in @@ -30,6 +30,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/configure b/configure old mode 100644 new mode 100755 index fd5be66..0985102 --- a/configure +++ b/configure @@ -1,11 +1,9 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.69. # # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -89,6 +87,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -133,6 +132,31 @@ export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh @@ -166,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi -test x\$exitcode = x0 || exit 1" +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && @@ -210,14 +235,25 @@ IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 fi if test x$as_have_required = xno; then : @@ -319,6 +355,14 @@ $as_echo X"$as_dir" | } # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take @@ -440,6 +484,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -474,16 +522,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -495,28 +543,8 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -1032,7 +1060,7 @@ Try \`$0 --help' for more information" $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1083,8 +1111,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1324,9 +1350,9 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.69 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1370,7 +1396,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1402,7 +1428,7 @@ $as_echo "$ac_try_echo"; } >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext + test -x conftest$ac_exeext }; then : ac_retval=0 else @@ -1416,7 +1442,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1429,7 +1455,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1484,7 +1510,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF @@ -1492,7 +1518,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1750,7 +1776,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;} || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -1883,7 +1909,7 @@ $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias @@ -1899,7 +1925,7 @@ fi $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -1996,7 +2022,7 @@ else set dummy ghc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_GHC+set}" = set; then : +if ${ac_cv_prog_GHC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$GHC"; then @@ -2008,7 +2034,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_GHC="ghc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2119,7 +2145,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2131,7 +2157,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2159,7 +2185,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2171,7 +2197,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2212,7 +2238,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2224,7 +2250,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2252,7 +2278,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2265,7 +2291,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue @@ -2311,7 +2337,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2323,7 +2349,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2355,7 +2381,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2367,7 +2393,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2410,7 +2436,7 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -2525,7 +2551,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -2568,7 +2594,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -2627,7 +2653,7 @@ $as_echo "$ac_try_echo"; } >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -2638,7 +2664,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2679,7 +2705,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -2689,7 +2715,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2726,7 +2752,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -2804,7 +2830,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -2813,8 +2839,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include -#include +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -2903,7 +2928,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu for ac_func in arc4random do : ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" -if test "x$ac_cv_func_arc4random" = x""yes; then : +if test "x$ac_cv_func_arc4random" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ARC4RANDOM 1 _ACEOF @@ -2929,7 +2954,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2949,7 +2974,7 @@ case $as_dir/ in #(( # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -3073,10 +3098,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -3108,7 +3144,7 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -3209,6 +3245,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -3404,16 +3441,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -3473,28 +3510,16 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -3516,7 +3541,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -3578,10 +3603,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -3670,7 +3695,7 @@ fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' @@ -3704,7 +3729,7 @@ do "testsuite/makewith/io/TestIO.conf") CONFIG_FILES="$CONFIG_FILES testsuite/makewith/io/TestIO.conf" ;; "testsuite/makewith/unsafeio/Unsafe.conf") CONFIG_FILES="$CONFIG_FILES testsuite/makewith/unsafeio/Unsafe.conf" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -3726,9 +3751,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -3736,12 +3762,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -3763,7 +3790,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -3791,7 +3818,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -3839,7 +3866,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -3871,7 +3898,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF @@ -3905,7 +3932,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -3917,8 +3944,8 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 @@ -4019,7 +4046,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -4038,7 +4065,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -4047,7 +4074,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -4073,8 +4100,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -4204,21 +4231,22 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; @@ -4229,20 +4257,20 @@ which seems to be undefined. Please make sure it is defined" >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ + mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; diff --git a/plugins.cabal b/plugins.cabal index 2b1b21c..b5d88c6 100644 --- a/plugins.cabal +++ b/plugins.cabal @@ -25,6 +25,7 @@ Tested-with: GHC == 7.4.* , GHC == 7.8.* , GHC == 7.10.* , GHC == 8.0.* + , GHC == 8.2.* extra-source-files: config.guess, config.h.in, config.mk.in, config.sub, configure, configure.ac, install.sh, Makefile, testsuite/makewith/io/TestIO.conf.in, diff --git a/src/System/Eval/Haskell.hs b/src/System/Eval/Haskell.hs index c0db6d2..68da73d 100644 --- a/src/System/Eval/Haskell.hs +++ b/src/System/Eval/Haskell.hs @@ -239,7 +239,7 @@ dynwrap expr nm mods = x = ident () ident () = unsafePerformIO $ - sequence (take 3 (repeat $ getStdRandom (randomR (97,122)) >>= return . chr)) + sequence (Prelude.take 3 (repeat $ getStdRandom (randomR (97,122)) >>= return . chr)) -- --------------------------------------------------------------------- -- unsafe wrapper diff --git a/src/System/Plugins/Consts.hs b/src/System/Plugins/Consts.hs index 26a9b4b..5142fae 100644 --- a/src/System/Plugins/Consts.hs +++ b/src/System/Plugins/Consts.hs @@ -43,8 +43,8 @@ sysPkgConf = "package.conf" -- | This code is from runtime_loader: -- The extension used by system modules. -sysPkgSuffix = ".o" -objSuf = sysPkgSuffix +sysPkgSuffix = ".a" +objSuf = ".o" hiSuf = ".hi" hsSuf = ".hs" #if defined(CYGWIN) || defined(__MINGW32__) diff --git a/src/System/Plugins/Env.hs b/src/System/Plugins/Env.hs index 39a245e..1826f7f 100644 --- a/src/System/Plugins/Env.hs +++ b/src/System/Plugins/Env.hs @@ -43,6 +43,7 @@ module System.Plugins.Env ( union, addStaticPkg, isStaticPkg, + rmStaticPkg, grabDefaultPkgConf, readPackageConf, lookupPkg @@ -69,7 +70,19 @@ import System.IO.Error ( catch, ioError, isDoesNotExistError ) import Control.Concurrent.MVar ( MVar(), newMVar, withMVar ) -import Distribution.Package hiding (depends, packageName, PackageName(..) +import GHC.Paths (libdir) +import DynFlags ( +#if MIN_VERSION_ghc(7,8,0) + Way(WayDyn), dynamicGhc, ways, +#endif + defaultDynFlags, initDynFlags) +import SysTools (initSysTools) + +import Distribution.Package hiding ( +#if MIN_VERSION_ghc(7,6,0) + Module, +#endif + depends, packageName, PackageName(..) #if MIN_VERSION_ghc(7,10,0) , installedPackageId #endif @@ -358,6 +371,12 @@ addStaticPkg pkg = modifyStaticPkgEnv env $ \set -> return $ S.insert pkg set isStaticPkg :: PackageName -> IO Bool isStaticPkg pkg = withStaticPkgEnv env $ \set -> return $ S.member pkg set +rmStaticPkg :: String -> IO Bool +rmStaticPkg pkg = do + (willRemove, s) <- withStaticPkgEnv env $ \s -> return (S.member pkg s, s) + if not willRemove then return False + else do modifyStaticPkgEnv env $ \s' -> return $ S.delete pkg s' + return True -- -- Package path, given a package name, look it up in the environment and -- return the path to all the libraries needed to load this package. @@ -382,7 +401,9 @@ lookupPkg pn = go [] pn go :: [PackageName] -> PackageName -> IO ([FilePath],[FilePath]) go seen p = do (ps, (f, g)) <- lookupPkg' p - static <- isStaticPkg p + static <- if not (null f) && null g + then addStaticPkg p >> return True + else isStaticPkg p (f', g') <- liftM unzip $ mapM (go (nub $ seen ++ ps)) (ps \\ seen) return $ (nub $ (concat f') ++ f, if static then [] else nub $ (concat g') ++ g) @@ -444,7 +465,16 @@ lookupPkg' p = withPkgEnvs env $ \fms -> go fms p #endif -- If we're loading dynamic libs we need the cbits to appear before the -- real packages. - libs <- mapM (findHSlib libdirs) (cbits ++ hslibs) + settings <- initSysTools (Just libdir) + dflags <- initDynFlags $ defaultDynFlags settings + libs <- mapM (findHSlib +#if MIN_VERSION_ghc(7,8,0) + (WayDyn `elem` ways dflags || dynamicGhc) +#else + False +#endif + libdirs) + (cbits ++ hslibs) #if defined(CYGWIN) || defined(__MINGW32__) windowsos <- catch (getEnv "OS") (\e -> if isDoesNotExistError e then return "Windows_98" else ioError e) @@ -490,23 +520,24 @@ lookupPkg' p = withPkgEnvs env $ \fms -> go fms p if b then return $ Just l -- found it! else findHSlib' dirs lib - findHSslib dirs lib = findHSlib' dirs $ lib ++ sysPkgSuffix + findHSslib dirs lib = findHSlib' dirs $ "lib" ++ lib ++ sysPkgSuffix findHSdlib dirs lib = findHSlib' dirs $ mkDynPkgName lib - -- Problem: sysPkgSuffix is ".o", but extra libraries could be - -- ".so" - -- Solution: first look for static library, if we don't find it - -- look for a dynamic version. - findHSlib :: [FilePath] -> String -> IO (Either String HSLib) - findHSlib dirs lib = do - static <- findHSslib dirs lib - case static of - Just file -> return $ Right $ Static file - Nothing -> do - dynamic <- findHSdlib dirs lib - case dynamic of - Just file -> return $ Right $ Dynamic file - Nothing -> return $ Left lib + findHSlib :: Bool -> [FilePath] -> String -> IO (Either String HSLib) + findHSlib dynonly dirs lib = do + -- Problem: sysPkgSuffix is ".a", but system packages could be dynamic, and + -- extra dynamic libraries could be needed even when using normal (static) linkage. + -- Solution: look for dynamic libraries only if using -dynamic; otherwise, use static + -- and add any other dynamic libraries found. + dl <- findHSdlib dirs lib + let rdl = case dl of + Just file -> Right $ Dynamic file + Nothing -> Left lib + if dynonly then return rdl else do + rsl <- findHSslib dirs lib + return $ case rsl of + Just file -> Right $ Static file + Nothing -> rdl findDLL :: [FilePath] -> String -> IO (Either String FilePath) findDLL [] lib = return (Left lib) diff --git a/src/System/Plugins/Load.hs b/src/System/Plugins/Load.hs index 696b212..bff1b21 100644 --- a/src/System/Plugins/Load.hs +++ b/src/System/Plugins/Load.hs @@ -70,12 +70,17 @@ import System.Plugins.Consts ( sysPkgSuffix, hiSuf, prefixUnderscore ) import System.Plugins.LoadTypes -- import Language.Hi.Parser +import Encoding (zEncodeString) import BinIface import HscTypes import Module (moduleName, moduleNameString) #if MIN_VERSION_ghc(8,0,0) +#if MIN_VERSION_Cabal(2,0,0) +import Module (installedUnitIdString) +#else import Module (unitIdString) +#endif #elif MIN_VERSION_ghc(7,10,0) import Module (packageKeyString) #else @@ -91,6 +96,7 @@ import Data.Typeable ( Typeable ) import Data.List ( isSuffixOf, nub, nubBy ) import Control.Monad ( when, filterM, liftM ) import System.Directory ( doesFileExist, removeFile ) +import Foreign.C ( CInt(..) ) import Foreign.C.String ( CString, withCString, peekCString ) #if !MIN_VERSION_ghc(7,2,0) @@ -173,7 +179,7 @@ load :: FilePath -- ^ object file -> IO (LoadStatus a) load obj incpaths pkgconfs sym = do - initLinker + initLinker_ $ fromIntegral 0 -- load extra package information mapM_ addPkgConf pkgconfs @@ -443,7 +449,8 @@ reload m@(Module{path = p, iface = hi}) sym = do -- | Call the initLinker function first, before calling any of the other -- functions in this module - otherwise you\'ll get unresolved symbols. --- initLinker :: IO () +initLinker :: IO () +initLinker = initLinker_ $ fromIntegral 0 -- our initLinker transparently calls the one in GHC -- @@ -466,8 +473,8 @@ loadFunction__ :: Maybe String -> String -> IO (Maybe a) loadFunction__ pkg m valsym - = do let symbol = prefixUnderscore++(maybe "" (\p -> encode p++"_") pkg) - ++encode m++"_"++(encode valsym)++"_closure" + = do let symbol = prefixUnderscore++(maybe "" (\p -> zEncodeString p++"_") pkg) + ++zEncodeString m++"_"++(zEncodeString valsym)++"_closure" #if DEBUG putStrLn $ "Looking for <<"++symbol++">>" #endif @@ -525,17 +532,21 @@ loadObject p ky@(Package k) = loadObject' p ky k loadObject' :: FilePath -> Key -> String -> IO Module loadObject' p ky k - | ("HSrts"++sysPkgSuffix) `isSuffixOf` p = return (emptyMod p) - - | otherwise = do alreadyLoaded <- isLoaded k when (not alreadyLoaded) $ do - r <- withCString p c_loadObj - when (not r) (panic $ "Could not load module `"++p++"'") - addModule k (emptyMod p) -- needs to Z-encode module name - return (emptyMod p) + let ld = if sysPkgSuffix `isSuffixOf` p + then c_loadArchive + else c_loadObj + r <- withCString p ld + when (not r) (panic $ "Could not load module or package `"++p++"'") + let hifile = replaceSuffix p hiSuf + exists <- doesFileExist hifile + hiface <- if exists then readBinIface' hifile else return undefined + let m = emptyMod p hiface + addModule k m + return m - where emptyMod q = Module q (mkModid q) Vanilla undefined ky + where emptyMod q hiface = Module q (mkModid q) Vanilla hiface ky -- | -- load a single object. no dependencies. You should know what you're @@ -711,7 +722,11 @@ loadDepends obj incpaths = do -- and find some packages to load, as well. let ps = dep_pkgs ds #if MIN_VERSION_ghc(8,0,0) +#if MIN_VERSION_Cabal(2,0,0) + ps' <- filterM loaded . map installedUnitIdString . nub $ map fst ps +#else ps' <- filterM loaded . map unitIdString . nub $ map fst ps +#endif #elif MIN_VERSION_ghc(7,10,0) ps' <- filterM loaded . map packageKeyString . nub $ map fst ps #elif MIN_VERSION_ghc(7,2,0) @@ -758,11 +773,14 @@ foreign import ccall unsafe "loadObj" foreign import ccall unsafe "unloadObj" c_unloadObj :: CString -> IO Bool +foreign import ccall unsafe "loadArchive" + c_loadArchive :: CString -> IO Bool + foreign import ccall unsafe "resolveObjs" c_resolveObjs :: IO Bool foreign import ccall unsafe "addDLL" c_addDLL :: CString -> IO CString -foreign import ccall unsafe "initLinker" - initLinker :: IO () +foreign import ccall unsafe "initLinker_" + initLinker_ :: CInt -> IO () diff --git a/src/System/Plugins/Utils.hs b/src/System/Plugins/Utils.hs index 1d2d124..bec328e 100644 --- a/src/System/Plugins/Utils.hs +++ b/src/System/Plugins/Utils.hs @@ -57,20 +57,33 @@ module System.Plugins.Utils ( ) where + #include "../../../config.h" import System.Plugins.Env ( isLoaded ) import System.Plugins.Consts ( objSuf, hiSuf, tmpDir ) --- import qualified System.MkTemp ( mkstemps ) + +import Foreign.C (CInt(..), CString, withCString) +import Foreign.C.Error (Errno, eEXIST, getErrno, errnoToIOError) +import System.Posix.Internals +import System.Posix.Types (CMode) import Control.Exception (IOException, catch) +import Data.Bits import Data.Char import Data.List -import Prelude hiding (catch) +import Prelude hiding (catch) -import System.IO +import System.IO hiding (openBinaryTempFile, openTempFile) +import System.Random (randomRIO) + +import GHC.IO.Encoding (getLocaleEncoding) +import GHC.IO.Handle.FD +import qualified GHC.IO.FD as FD import System.Environment ( getEnv ) import System.Directory ( doesFileExist, getModificationTime, removeFile ) +import System.FilePath (pathSeparator) + -- --------------------------------------------------------------------- -- some misc types we use @@ -90,31 +103,129 @@ hWrite hdl src = hPutStr hdl src >> hClose hdl >> return () -- --------------------------------------------------------------------- --- | mkstemps. +-- | openTempFile. -- --- We use the Haskell version now... it is faster than calling into --- mkstemps(3). +-- System.IO.openTempFile uses undesirable characters in its filenames, which +-- breaks e.g. merge and other functions that try to compile Haskell source. +-- Sadly, this means we must provide our own secure temporary file facility. -- --- mkstemps :: String -> Int -> IO (String,Handle) --- mkstemps path slen = do --- m_v <- System.MkTemp.mkstemps path slen --- case m_v of Nothing -> error "mkstemps : couldn't create temp file" --- Just v' -> return v' +openTempFile :: FilePath -- ^ Directory in which to create the file + -> String -- ^ File name prefix. If the prefix is \"fooie\", + -- the full name will be \"fooie\" followed by six + -- random alphanumeric characters followed by, if + -- given, the suffix. Should not contain any path + -- separator characters. + -> String -- ^ File name suffix. Should not contain any path + -- separator characters. + -> IO (FilePath, Handle) +openTempFile tmp_dir pfx sfx + = openTempFile' "openTempFile" tmp_dir pfx sfx False 0o600 -{- +-- | Like 'openTempFile', but opens the file in binary mode. See 'openBinaryFile' for more comments. +openBinaryTempFile :: FilePath -> String -> String -> IO (FilePath, Handle) +openBinaryTempFile tmp_dir pfx sfx + = openTempFile' "openBinaryTempFile" tmp_dir pfx sfx True 0o600 -mkstemps path slen = do - withCString path $ \ ptr -> do - let c_slen = fromIntegral $ slen+1 - fd <- throwErrnoIfMinus1 "mkstemps" $ c_mkstemps ptr c_slen - name <- peekCString ptr - hdl <- fdToHandle fd - return (name, hdl) +-- | Like 'openTempFile', but uses the default file permissions +openTempFileWithDefaultPermissions :: FilePath -> String -> String + -> IO (FilePath, Handle) +openTempFileWithDefaultPermissions tmp_dir pfx sfx + = openTempFile' "openTempFileWithDefaultPermissions" tmp_dir pfx sfx False 0o666 -foreign import ccall unsafe "mkstemps" c_mkstemps :: CString -> CInt -> IO Fd +-- | Like 'openBinaryTempFile', but uses the default file permissions +openBinaryTempFileWithDefaultPermissions :: FilePath -> String -> String + -> IO (FilePath, Handle) +openBinaryTempFileWithDefaultPermissions tmp_dir pfx sfx + = openTempFile' "openBinaryTempFileWithDefaultPermissions" tmp_dir pfx sfx True 0o666 --} +badfnmsg :: String +badfnmsg = "openTempFile': Template string must not contain path separator characters: " + +openTempFile' :: String -> FilePath -> String -> String -> Bool -> CMode + -> IO (FilePath, Handle) +openTempFile' loc tmp_dir pfx sfx binary mode + | pathSeparator `elem` pfx + = fail $ badfnmsg++pfx + | pathSeparator `elem` sfx + = fail $ badfnmsg++sfx + | otherwise = findTempName + where + findTempName = do + filename <- mkTempFileName tmp_dir pfx sfx + r <- openNewFile filename binary mode + case r of + FileExists -> findTempName + OpenNewError errno -> ioError (errnoToIOError loc errno Nothing (Just tmp_dir)) + NewFileCreated fd -> do + (fD,fd_type) <- FD.mkFD fd ReadWriteMode Nothing{-no stat-} + False{-is_socket-} + True{-is_nonblock-} + + enc <- getLocaleEncoding + h <- mkHandleFromFD fD fd_type filename ReadWriteMode False{-set non-block-} (Just enc) + + return (filename, h) + +mkTempFileName :: FilePath -> String -> String -> IO String +mkTempFileName dir pfx sfx = do + let rs = filter isAlphaNum ['0'..'z'] + maxInd = length rs - 1 + rchoose = do + i <- randomRIO (0, maxInd) + return (rs !! i) + rnd <- sequence $ replicate 6 rchoose + return $ dir pfx ++ rnd ++ sfx + +data OpenNewFileResult + = NewFileCreated CInt + | FileExists + | OpenNewError Errno + +openNewFile :: FilePath -> Bool -> CMode -> IO OpenNewFileResult +openNewFile filepath binary mode = do + let oflags1 = rw_flags .|. o_EXCL + + binary_flags + | binary = o_BINARY + | otherwise = 0 + + oflags = oflags1 .|. binary_flags + fd <- withFilePath filepath $ \ f -> + c_open f oflags mode + if fd < 0 + then do + errno <- getErrno + case errno of + _ | errno == eEXIST -> return FileExists +#ifdef mingw32_HOST_OS + -- If c_open throws EACCES on windows, it could mean that filepath is a + -- directory. In this case, we want to return FileExists so that the + -- enclosing openTempFile can try again instead of failing outright. + -- See bug #4968. + _ | errno == eACCES -> do + withCString filepath $ \path -> do + -- There is a race here: the directory might have been moved or + -- deleted between the c_open call and the next line, but there + -- doesn't seem to be any direct way to detect that the c_open call + -- failed because of an existing directory. + exists <- c_fileExists path + return $ if exists + then FileExists + else OpenNewError errno +#endif + _ -> return (OpenNewError errno) + else return (NewFileCreated fd) + +#ifdef mingw32_HOST_OS +foreign import ccall "file_exists" c_fileExists :: CString -> IO Bool +#endif + +-- XXX Copied from GHC.Handle +std_flags, output_flags, rw_flags :: CInt +std_flags = o_NONBLOCK .|. o_NOCTTY +output_flags = std_flags .|. o_CREAT +rw_flags = output_flags .|. o_RDWR -- --------------------------------------------------------------------- -- | create a new temp file, returning name and handle. @@ -126,10 +237,8 @@ mkTemp = do tmpd <- catch (getEnv "TMPDIR") (\ (_ :: IOException) -> return tmp mkTempIn :: String -> IO (String, Handle) mkTempIn tmpd = do - -- XXX (tmpf,hdl) <- mkstemps (tmpd++"/MXXXXXXXXX.hs") 3 - - (tmpf, hdl) <- openTempFile tmpd "MXXXXX.hs" - let modname = mkModid $ dropSuffix tmpf + (tmpf, hdl) <- openTempFile tmpd "Hsplugins" ".hs" + let modname = mkModid tmpf if and $ map (\c -> isAlphaNum c && c /= '_') modname then return (tmpf,hdl) else panic $ "Illegal characters in temp file: `"++tmpf++"'" diff --git a/testsuite/build.mk b/testsuite/build.mk index 75d66e0..18291b6 100644 --- a/testsuite/build.mk +++ b/testsuite/build.mk @@ -13,7 +13,7 @@ REALBIN= ./Main API_OBJ= api/API.o INCLUDES= -i$(TOP)/testsuite/$(TEST)/api -GHCFLAGS= -O0 -cpp -fglasgow-exts +GHCFLAGS= -rdynamic -O0 -cpp -fglasgow-exts .SUFFIXES : .o .hs .hi .lhs .hc .s @@ -26,7 +26,7 @@ $(BIN) : $(PRIOR_OBJS) $(API_OBJ) $(SRC) $(EXTRA_OBJS) # Standard suffix rules .o.hi: @: -.hs.o: +.hs.o: $(API_OBJ) @$(GHC) $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) -c $< clean: diff --git a/testsuite/dynload/io/TestIO.hs b/testsuite/dynload/io/TestIO.hs index be13510..fb8d489 100644 --- a/testsuite/dynload/io/TestIO.hs +++ b/testsuite/dynload/io/TestIO.hs @@ -1,4 +1,3 @@ -{-# OPTIONS -fglasgow-exts -cpp #-} -- -- Copyright (c) 2004 Don Stewart - http://www.cse.unsw.edu.au/~dons -- LGPL version 2.1 or later (see http://www.gnu.org/copyleft/lesser.html) @@ -9,6 +8,8 @@ module TestIO ( resource_dyn ) where import API import Data.Dynamic +import Control.Exception (SomeException, catch) + import System.IO import System.Posix.Types ( ProcessID, Fd ) import System.Posix.Process ( forkProcess, executeFile, getProcessID ) @@ -26,7 +27,7 @@ resource = testio { field = date } -- call a shell command , returning it's output -- date :: IO String -date = do (hdl,_,_) <- catch (popen "/bin/date") (\_->error "popen failed") +date = do (hdl,_,_) <- catch (popen "/bin/date") (\(_ :: SomeException)->error "popen failed") hGetLine hdl ------------------------------------------------------------------------ diff --git a/testsuite/dynload/io/api/API.hs b/testsuite/dynload/io/api/API.hs index 671ee2e..b408265 100644 --- a/testsuite/dynload/io/api/API.hs +++ b/testsuite/dynload/io/api/API.hs @@ -1,19 +1,20 @@ -{-# OPTIONS -fglasgow-exts #-} - module API where import Data.Typeable data TestIO = TestIO { field :: IO String +#if __GLASGOW_HASKELL__ >= 800 + } deriving Typeable +#else } - instance Typeable TestIO where #if __GLASGOW_HASKELL__ >= 603 typeOf i = mkTyConApp (mkTyCon "API.TestIO") [] #else typeOf i = mkAppTy (mkTyCon "API.TestIO") [] #endif +#endif testio :: TestIO testio = TestIO { field = return "default value" } diff --git a/testsuite/dynload/io/prog/Main.hs b/testsuite/dynload/io/prog/Main.hs index 4fe15c5..ddabc5f 100644 --- a/testsuite/dynload/io/prog/Main.hs +++ b/testsuite/dynload/io/prog/Main.hs @@ -1,12 +1,13 @@ import System.Plugins + import API main = do - m_v <- dynload "../TestIO.o" ["../api"] - [] "resource_dyn" - case m_v of - LoadFailure _ -> error "couldn't compile" - LoadSuccess _ v -> do - s <- field v - if s /= [] then print True else print False + m_v <- dynload "../TestIO.o" ["../api"] + [] "resource_dyn" :: IO (LoadStatus TestIO) + case m_v of + LoadFailure _ -> error "couldn't link" + LoadSuccess _ v -> do + s <- field v + if s /= "" then print True else print False diff --git a/testsuite/load/plain/Makefile b/testsuite/load/plain/Makefile new file mode 100644 index 0000000..1189a8b --- /dev/null +++ b/testsuite/load/plain/Makefile @@ -0,0 +1,6 @@ +TEST=load/plain + +EXTRA_OBJS=TestIO.o + +TOP=../../.. +include ../../build.mk diff --git a/testsuite/load/plain/TestIO.hs b/testsuite/load/plain/TestIO.hs new file mode 100644 index 0000000..54c861b --- /dev/null +++ b/testsuite/load/plain/TestIO.hs @@ -0,0 +1,11 @@ +module TestIO (resource) where + +import Control.Monad (forever) + +import API + +resource :: CLIInterface +resource = testio { repl = loop } + +loop :: IO () +loop = forever $ getLine >>= putStrLn diff --git a/testsuite/load/plain/api/API.hs b/testsuite/load/plain/api/API.hs new file mode 100644 index 0000000..587f7b8 --- /dev/null +++ b/testsuite/load/plain/api/API.hs @@ -0,0 +1,10 @@ +module API(CLIInterface(..), testio) where + +import Data.Typeable + +data CLIInterface = CLIInterface { + repl :: IO () +} deriving Typeable + +testio :: CLIInterface +testio = CLIInterface { repl = return () } diff --git a/testsuite/load/plain/prog/Main.hs b/testsuite/load/plain/prog/Main.hs new file mode 100644 index 0000000..d8338f9 --- /dev/null +++ b/testsuite/load/plain/prog/Main.hs @@ -0,0 +1,22 @@ +module Main (main) where + +import Control.Exception (handle) + +import System.Plugins + +import API + +fexn :: IOError -> IO () +fexn = print + +main :: IO () +main = handle fexn $ do + mf <- load "../TestIO.o" ["../api"] [] "resource" + case mf of + LoadFailure _ -> error "nope" + LoadSuccess _ v -> do + putStrLn "success" + engage v + +engage :: CLIInterface -> IO () +engage plugin = repl plugin From c475a462231cd10d4dc14a21d51d2e79b71b029f Mon Sep 17 00:00:00 2001 From: Mark Laws Date: Sun, 21 Jan 2018 01:14:49 +0900 Subject: [PATCH 2/2] Unquiet build process --- testsuite/build.mk | 8 ++++---- testsuite/check.mk | 2 +- testsuite/eval.mk | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/testsuite/build.mk b/testsuite/build.mk index 18291b6..54774b3 100644 --- a/testsuite/build.mk +++ b/testsuite/build.mk @@ -20,14 +20,14 @@ GHCFLAGS= -rdynamic -O0 -cpp -fglasgow-exts all: $(BIN) $(BIN) : $(PRIOR_OBJS) $(API_OBJ) $(SRC) $(EXTRA_OBJS) - @rm -f $@ - @$(GHC) --make -o $@ $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) $(API) $(SRC) + rm -f $@ + $(GHC) --make -o $@ $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) $(API) $(SRC) # Standard suffix rules .o.hi: - @: + : .hs.o: $(API_OBJ) - @$(GHC) $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) -c $< + $(GHC) $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) -c $< clean: find . -name '*~' -exec rm {} \; diff --git a/testsuite/check.mk b/testsuite/check.mk index b07d859..2ad08d9 100644 --- a/testsuite/check.mk +++ b/testsuite/check.mk @@ -1,7 +1,7 @@ include $(TOP)/config.mk check: $(BIN) - @(cd $(BINDIR) ;\ + (cd $(BINDIR) ;\ expected="expected" ;\ if [ -f "expected" -o -f "expected.$(GLASGOW_HASKELL)" ] ;\ then \ diff --git a/testsuite/eval.mk b/testsuite/eval.mk index 93000b4..ae61c09 100644 --- a/testsuite/eval.mk +++ b/testsuite/eval.mk @@ -12,14 +12,14 @@ REALBIN= ./$(BIN) all: $(BIN) $(BIN): $(SRC) $(OBJS) - @rm -f $@ - @$(GHC) --make -fglasgow-exts $(GHCFLAGS) $(PKGFLAGS) $(EXTRAFLAGS) $(SRC) + rm -f $@ + $(GHC) --make -fglasgow-exts $(GHCFLAGS) $(PKGFLAGS) $(EXTRAFLAGS) $(SRC) # Standard suffix rules .o.hi: - @: + : .hs.o: - @$(GHC) $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) -c $< + $(GHC) $(INCLUDES) $(PKGFLAGS) $(GHCFLAGS) $(EXTRAFLAGS) -c $< clean: - @rm -rf *.hi *.o *~ $(BIN) + rm -rf *.hi *.o *~ $(BIN)