Skip to content

Commit

Permalink
nrnivmodl under cmake no longer uses symbolic links. (#850)
Browse files Browse the repository at this point in the history
* nrnivmodl under cmake no longer uses symbolic links.

* windows has different signature for mkdir

* missed one

* .libs/libnrnmech.sh may not be a symlink.

* Accept reviewer suggestions.

-I<mod_file_location> before $(INCLUDES)

* Uniform 2 space per level indentation.
  But note that Make rules require a tab for indentation.

* Handle spaces in paths to mod file

* extern cfiles can be a ';' separated list of c files

* extern cfiles now is extern nrnivmodl_cfiles to list ';' separated c files.

* nrnivmodl file and folder name arg checking.

* print args only on error

* add some comments

Co-authored-by: Pramod Kumbhar <pramod.kumbhar@epfl.ch>
  • Loading branch information
nrnhines and pramodk committed Dec 10, 2020
1 parent 59e5538 commit 33c8857
Show file tree
Hide file tree
Showing 8 changed files with 403 additions and 164 deletions.
266 changes: 199 additions & 67 deletions bin/nrnivmodl.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,34 @@ set -e

ARCH=@host_cpu@
MODSUBDIR=@modsubdir@
USER_PWD="`pwd`"

UsingCMake="no"
@USING_CMAKE_TRUE@UsingCMake="yes"

if test "x${NRNHOME}" = x ; then
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
else
prefix="$NRNHOME"
exec_prefix="${prefix}/${ARCH}"
@USING_CMAKE_FALSE@bindir="${prefix}/${ARCH}/bin"
@USING_CMAKE_FALSE@libdir="${prefix}/${ARCH}/lib"
@USING_CMAKE_TRUE@bindir="${prefix}/bin"
@USING_CMAKE_TRUE@libdir="${prefix}/lib"
prefix="$NRNHOME"
exec_prefix="${prefix}/${ARCH}"
@USING_CMAKE_FALSE@bindir="${prefix}/${ARCH}/bin"
@USING_CMAKE_FALSE@libdir="${prefix}/${ARCH}/lib"
@USING_CMAKE_TRUE@bindir="${prefix}/bin"
@USING_CMAKE_TRUE@libdir="${prefix}/lib"
fi

if test "${NRNHOME_EXEC}" != "" ; then
exec_prefix="${NRNHOME_EXEC}"
bindir="${exec_prefix}/bin"
libdir="${exec_prefix}/lib"
exec_prefix="${NRNHOME_EXEC}"
bindir="${exec_prefix}/bin"
libdir="${exec_prefix}/lib"
fi

# Besides NRNHOME, one may set NRNBIN to override the default location of user binaries
if test "x$NRNBIN" = "x"; then
NRNBIN=$bindir
NRNBIN=$bindir
fi

export prefix
Expand Down Expand Up @@ -57,84 +61,186 @@ if [ "$1" = "-loadflags" ] ; then
shift
fi

if [ ! -d $MODSUBDIR ] ; then
echo "Creating $MODSUBDIR directory for .o files."
echo
mkdir $MODSUBDIR
fi

pwd

# Mod file paths may contain spaces which make variable lists of those
# hard to manage as space is the item separator. Furthermore, when a
# path is used, sometimes the spaces must be escaped (eg. a Makefile
# dependency pattern, and sometimes it is more useful for readability to
# enclose the path in "". To work around this issue, when creating a list
# of paths, translate the spaces for each item to +++ and after retrieval
# of an item, retranslate back to either a space or an escaped space.
# Only do this for cmake

hide_spaces() {
echo "$1" | sed 's/ /+++/g'
}
unhide_spaces() {
echo "$1" | sed 's/+++/ /g'
}
escape_spaces() {
echo "$1" | sed 's/+++/\\ /g'
}

# files is the complete list of mod files to process
files=""
incs=""
@USING_CMAKE_FALSE@incs=""
if test $# -gt 0 ; then
for i in "$@" ; do
if test -d "$i" ; then
set +e
files="$files $(unset LC_ALL; ls $i/*.mod)"
incs="$incs $(unset LC_ALL; ls $i/*.inc)"
set -e
else
files="$files $i"
fi
done
for i in "$@" ; do
i_hide=`hide_spaces "$i"`
if test -d "$i" ; then
set +e
if test "$UsingCMake" = "yes" ; then
for j in $(cd "$i"; unset LC_ALL; ls *.mod) ; do
files="$files $i_hide/$j"
done
else
files="$files $(unset LC_ALL; ls $i/*.mod)"
incs="$incs $(unset LC_ALL; ls $i/*.inc)"
fi
set -e
else
if test "$UsingCMake" = "yes" ; then
if test -e "$i" -o -e "$i.mod" ; then
files="$files $i_hide"
else
echo "Arg Error: \"$i\" is not a folder or mod file name or prefix"

echo ""
echo -n " Mod file, folder args:"
for j in "$@" ; do
echo -n " \"$j\""
done
echo ""

exit 1
fi
else
files="$files $i"
fi
fi
done
else
# Unset LC_ALL for consistent mod order
files=$(unset LC_ALL; ls *.mod)
# Unset LC_ALL for consistent mod order
files=$(unset LC_ALL; ls *.mod)
fi

files=`echo "$files" | sed 's/^ *//'`

mfiles=""
base_names=""
for i in $files ; do
mfiles="$mfiles `basename $i`"
base_names="$base_names `basename -s .mod $i`"
done
mfiles=`echo "$mfiles" | sed 's/^ *//'`

echo $files
echo $mfiles
if test "$UsingCMake" = "yes" ; then
echo -n "Mod files:"
for i in $files ; do
base_name=`basename -s .mod "$i"`
dir_name=`dirname "$i"`
echo -n " \"`unhide_spaces $dir_name`/$base_name.mod\""
done
echo ""
echo ""
fi

if [ ! -d $MODSUBDIR ] ; then
echo "Creating $MODSUBDIR directory for .o files."
echo
mkdir $MODSUBDIR
fi

files=`echo "$files" | sed 's/\.mod//g'`

if test "$files" = '*' ; then
files=""
files=""
fi

cd $MODSUBDIR
mdir=`pwd`
for i in $files; do
rm -f "`basename $i`".mod
ln -s ../$i.mod .
done
mdir="`pwd`"

if test "$incs" != "" ; then
for i in $incs ; do
rm -f "`basename $i`"
ln -s ../$i .
done
fi
if test "$UsingCMake" = "yes" ; then
# construct file to be included by makefile to specify mod to c rule when
# executed in $MODSUBDIR (child folder of launch location folder)
MODMAKE=makemod2c_inc
echo "" > $MODMAKE
for i in $files ; do
case "$i" in
/*) f=$i;; # absolute, fine as is
*) f=../$i;; # relative
esac
base_name="`basename $f`"
dir_name="`dirname $f`"
# Note: indentation for shell lines in make rules must be a tab
echo "\
./$base_name.c: `escape_spaces "$f.mod"`
@printf \" -> \$(C_GREEN)NMODL\$(C_RESET) \$<\\\n\"
(cd \"`unhide_spaces $dir_name`\"; MODLUNIT=\$(NRNUNITS) \$(NOCMODL) $base_name.mod -o \"$mdir\")
bfiles=`echo "$mfiles" | sed 's/\.mod//g'`
./$base_name.o: ./$base_name.c
@printf \" -> \$(C_GREEN)Compiling\$(C_RESET) \$<\\\n\"
\$(COMPILE) -I\"`unhide_spaces $dir_name`\" \$(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c \$< -o \$@
" >> $MODMAKE
done
if test "$nrnivmodl_cfiles" != "" ; then
# I find it very difficult to construct shell variables which are
# space separated lists of items containing spaces. So, for a cmake build,
# the nrnivmodl_cfiles variable is required to be a ';' separated list
# of c files which may contain spaces.
# Save the Internal Field Separator and interpret variables as ';'
# separated list of items (which may contain spaces). Restore after
# processing nrnivmodl_cfiles.
ifs="$IFS"
IFS=';'
for i in $nrnivmodl_cfiles ; do
i_hide=`hide_spaces "$i"`
case "$i_hide" in
/*) f=$i_hide;; # absolute, fine as is
*) f=../$i_hide;; # relative
esac
base_name="`basename -s .c $f`"
dir_name="`dirname $f`"
echo "\
./$base_name.o: `escape_spaces "$f"`
@printf \" -> \$(C_GREEN)Compiling\$(C_RESET) \$<\\\n\"
(cd \"`unhide_spaces $dir_name`\"; \$(COMPILE) \$(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $base_name.c -o \"$mdir/$base_name.o\")
" >> $MODMAKE
done
IFS="$ifs"
fi
else
for i in $files; do
rm -f "`basename $i`".mod
ln -s ../$i.mod .
done

for i in $cfiles; do
rm -f $i
ln -s ../$i .
done
if test "$incs" != "" ; then
for i in $incs ; do
rm -f "`basename $i`"
ln -s ../$i .
done
fi

for i in $nrnivmodl_cfiles; do
rm -f "$i"
ln -s "../$i" .
done
fi

COBJS=
MODOBJS=
if [ `echo "\n"` ] ; then
newline="\n"
newline="\n"
else
newline="\\\\n"
newline="\\\\n"
fi

echo '#include <stdio.h>
#include "hocdec.h"
extern int nrnmpi_myid;
extern int nrn_nobanner_;
' > mod_func.c
for i in $bfiles ; do
echo 'extern void _'$i'_reg(void);'
for i in $base_names ; do
echo 'extern void _'$i'_reg(void);'
done >> mod_func.c
echo '
void modl_reg(){
Expand All @@ -144,25 +250,51 @@ void modl_reg(){

for i in $files
do
echo ' fprintf(stderr," '$i'.mod");'
echo ' fprintf(stderr," \"'`unhide_spaces "$i"`'.mod\"");'
done >>mod_func.c

echo ' fprintf(stderr, "'$newline'");
}' >>mod_func.c

for i in $bfiles; do
echo ' _'$i'_reg();'
MODOBJS="$MODOBJS $i.o"
for i in $base_names; do
echo ' _'$i'_reg();'
@USING_CMAKE_TRUE@MODOBJS="$MODOBJS ./$i.o"
@USING_CMAKE_FALSE@MODOBJS="$MODOBJS $i.o"
done >> mod_func.c

echo "}" >> mod_func.c

if test -n "$nrnivmodl_cfiles" ; then
if test "$UsingCMake" = "yes" ; then
sp=""
COBJS=""
ifs="$IFS"
IFS=';'
for i in $nrnivmodl_cfiles ; do
base_name=`basename -s .c "$i"`
COBJS="${COBJS}${sp}./${base_name}.o"
sp=" "
done
IFS="$ifs"
else
COBJS=`echo "$nrnivmodl_cfiles" | sed 's/\.c/.o/g'`
fi
fi

if test -n "$cfiles" ; then
COBJS=`echo "$cfiles" | sed 's/\.c/.o/g'`
echo "COBJS='$COBJS'"
# call nrnivmodl-core if CoreNEURON is enabled and requested via CLI
if [ "$LinkCoreNEURON" = true ] ; then
:
@USING_CMAKE_FALSE@ printf "ERROR : CoreNEURON is not compatible with autotools, build with CMake build system!\n"
@USING_CMAKE_FALSE@ exit 1
@USING_CMAKE_TRUE@@CORENEURON_ENABLED_FALSE@ printf "ERROR : CoreNEURON support is not enabled!\n"
@USING_CMAKE_TRUE@@CORENEURON_ENABLED_FALSE@ exit 1
@USING_CMAKE_TRUE@@CORENEURON_ENABLED_TRUE@ cd $USER_PWD
@USING_CMAKE_TRUE@@CORENEURON_ENABLED_TRUE@ $bindir/nrnivmodl-core $MODSUBDIR
@USING_CMAKE_TRUE@@CORENEURON_ENABLED_TRUE@ cd $MODSUBDIR
fi

@NRN_BINARY_SPECIAL_TRUE@@USING_CMAKE_TRUE@make -j 4 -f "${MAKEFILEDIR}/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "COBJFILES=$COBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" special &&
@NRN_BINARY_SPECIAL_TRUE@@USING_CMAKE_TRUE@make -j 4 -f "${MAKEFILEDIR}/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "COBJFILES=$COBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" "LinkCoreNEURON=$LinkCoreNEURON" special &&
@NRN_BINARY_SPECIAL_TRUE@@USING_CMAKE_FALSE@make -j 4 -f "${MAKEFILEDIR}/nrniv_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "COBJFILES=$COBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" special &&
@NRN_BINARY_SPECIAL_TRUE@ echo "Successfully created $MODSUBDIR/special"

Expand All @@ -172,7 +304,7 @@ fi
@NRN_BINARY_SPECIAL_FALSE@ mdir='${NRNHOME}'/share/nrn/demo/release/${MODSUBDIR}
@NRN_BINARY_SPECIAL_FALSE@fi
@NRN_BINARY_SPECIAL_FALSE@@USING_CMAKE_FALSE@make -j 4 -f "$MAKEFILEDIR/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODLO" "COBJFILES=$CLO" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" libnrnmech.la
@NRN_BINARY_SPECIAL_FALSE@@USING_CMAKE_TRUE@make -j 4 -f "$MAKEFILEDIR/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "COBJFILES=$COBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" libnrnmech.la VERBOSE=1
@NRN_BINARY_SPECIAL_FALSE@@USING_CMAKE_TRUE@make -j 4 -f "$MAKEFILEDIR/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "COBJFILES=$COBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" "LinkCoreNEURON=$LinkCoreNEURON" mech_lib_shared VERBOSE=1
@NRN_BINARY_SPECIAL_FALSE@ echo '#!/bin/sh
@NRN_BINARY_SPECIAL_FALSE@if test "x${NRNHOME}" = "x" ; then
@NRN_BINARY_SPECIAL_FALSE@ NRNHOME='"\"${prefix}\""'
Expand Down
Loading

0 comments on commit 33c8857

Please sign in to comment.