1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2025-01-03 10:06:09 +01:00

Worked on Makefiles

This commit is contained in:
Anthony Scemama 2020-10-16 13:58:05 +02:00
parent 32d633bfb6
commit 4236b33a4f
7 changed files with 251 additions and 42 deletions

3
src/.gitignore vendored
View File

@ -1,3 +1,6 @@
*.o *.o
*.c *.c
*.h *.h
*~
*.so
Makefile.generated

View File

@ -1,30 +1,24 @@
CC=gcc CC=gcc
CFLAGS=-fexceptions -Wall -Werror -Wpedantic -Wextra CFLAGS=-fPIC -fexceptions -Wall -Werror -Wpedantic -Wextra
FC=gfortran FC=gfortran
FFLAGS=-fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant -Wuninitialized -fbacktrace -ffpe-trap=zero,overflow,underflow -finit-real=nan FFLAGS=-fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant -Wuninitialized -fbacktrace -ffpe-trap=zero,overflow,underflow -finit-real=nan
ORG_SOURCE_FILES=qmckl_context.org export CC CFLAGS FC FFLAGS
OBJECT_FILES=$(patsubst %.org,%.o,$(ORG_SOURCE_FILES))
ORG_SOURCE_FILES=$(wildcard qmckl*.org)
OBJECT_FILES=$(filter-out $(EXCLUDED_OBJECTS), $(patsubst %.org,%.o,$(ORG_SOURCE_FILES)))
.PHONY: clean .PHONY: clean
.SECONDARY: # Needed to keep the produced C and Fortran files
all: $(OBJECT_FILES) libqmckl.so: Makefile.generated
$(MAKE) -f Makefile.generated
%.c %.h: %.org
emacs --quick --no-init-file --batch --eval "(require 'org)" --eval '(org-babel-tangle-file "$^")'
%.c %.h %_f.f90: %.org
emacs --quick --no-init-file --batch --eval "(require 'org)" --eval '(org-babel-tangle-file "$^")'
%.o: %.c
$(CC) $(CFLAGS) -c $*.c -o $*.o
%.o: %.f90
$(FC) $(FFLAGS) -c $*.f90 -o $*.o
clean: clean:
rm -f qmckl_*.f90 qmckl_*.c qmckl_*.o qmckl_*.h rm -f qmckl_*.f90 qmckl_*.c qmckl_*.o qmckl_*.h Makefile.generated libqmckl.so
Makefile.generated: $(ORG_SOURCE_FILES) Makefile create_makefile.sh
./create_makefile.sh $(ORG_SOURCE_FILES)

View File

@ -14,13 +14,17 @@
The code is extracted from the org files using Emacs as a command-line The code is extracted from the org files using Emacs as a command-line
tool in the =Makefile=, and then the produced files are compiled. tool in the =Makefile=, and then the produced files are compiled.
If the name of the file is =xxx.org=, the name of the produced C
files should be =xxx.c= and =xxx.h= and the name of the produced
Fortran files should be =xxx.f90=
*** Source code editing *** Source code editing
Any text editor can be used to edit org-mode files. For a better Any text editor can be used to edit org-mode files. For a better
user experience Emacs is recommended. user experience Emacs is recommended.
For users hating Emacs, it is good to know that Emacs can behave For users hating Emacs, it is good to know that Emacs can behave
like Vim when switched into ``Evil'' mode. There also exists like Vim when switched into ``Evil'' mode. There also exists
[[https://www.spacemacs.org][Spacemacs]] which is particularly well adapted to Vim users. [[https://www.spacemacs.org][Spacemacs]] which helps the transition for Vim users.
For users with a preference for Jupyter notebooks, the following For users with a preference for Jupyter notebooks, the following
script can convert jupyter notebooks to org-mode files: script can convert jupyter notebooks to org-mode files:

69
src/create_makefile.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
OUTPUT=Makefile.generated
# Tangle org files
emacsclient -a "" \
--socket-name=org_to_code \
--eval "(require 'org)"
for INPUT in $@ ; do
emacsclient \
--no-wait \
--socket-name=org_to_code \
--eval "(org-babel-tangle-file \"$INPUT\")"
done
emacsclient \
--no-wait \
--socket-name=org_to_code \
--eval '(kill-emacs)'
# Create the list of *.o files to be created
OBJECTS=""
for i in $(ls qmckl_*.c) ; do
FILE=${i%.c}
OBJECTS="${OBJECTS} ${FILE}.o"
done >> $OUTPUT
for i in $(ls qmckl_*.f90) ; do
FILE=${i%.f90}
OBJECTS="${OBJECTS} ${FILE}.o"
done >> $OUTPUT
# Write the Makefile
cat << EOF > $OUTPUT
CC=$CC
CFLAGS=$CFLAGS
FC=$FC
FFLAGS=$FFLAGS
OBJECT_FILES=$OBJECTS
libqmckl.so: \$(OBJECT_FILES)
\$(CC) -shared \$(OBJECT_FILES) -o libqmckl.so
%.o: %.c
\$(CC) \$(CFLAGS) -c \$*.c -o \$*.o
%.o: %.f90
\$(FC) \$(FFLAGS) -c \$*.f90 -o \$*.o
EOF
for i in $(ls qmckl_*.c) ; do
FILE=${i%.c}
echo "${FILE}.o: ${FILE}.c " *.h
done >> $OUTPUT
for i in $(ls qmckl_*.f90) ; do
FILE=${i%.f90}
echo "${FILE}.o: ${FILE}.f90"
done >> $OUTPUT

38
src/org_to_code.sh Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
if [[ -z $1 ]] ; then
echo "Usage: $0 <FILE.org>"
exit 1;
fi
if [[ -z $6 ]] ; then
# Few file to tangle
for INPUT in $@ ; do
emacs \
--quick \
--no-init-file \
--batch \
--eval "(require 'org)" \
--eval "(org-babel-tangle-file \"$INPUT\")"
done
else
# Multiple files to tangle, so we use the emacs server to speed up thing
emacsclient -a "" \
--socket-name=org_to_code \
--eval "(require 'org)"
for INPUT in $@ ; do
emacsclient \
--no-wait \
--socket-name=org_to_code \
--eval "(org-babel-tangle-file \"$INPUT\")"
done
emacsclient \
--no-wait \
--socket-name=org_to_code \
--eval '(kill-emacs)'
fi

47
src/qmckl.org Normal file
View File

@ -0,0 +1,47 @@
# -*- mode: org -*-
# vim: syntax=c
#+TITLE: QMCkl C header
This file is included in all other C header files, and produces the
=qmckl.h= header file.
#+BEGIN_SRC C :tangle qmckl.h
#ifndef QMCKL_H
#define QMCKL_H
#+END_SRC
* Constants
** Success/failure
These are the codes returned by the functions to indicate success
or failure. All such functions should have as a return type =qmckl_exit_code=.
#+BEGIN_SRC C :tangle qmckl.h
#define QMCKL_SUCCESS 0
#define QMCKL_FAILURE 1
typedef int qmckl_exit_code;
#+END_SRC
** Precision-related constants
#+BEGIN_SRC C :tangle qmckl.h
#define QMCKL_DEFAULT_PRECISION 53
#define QMCKL_DEFAULT_RANGE 2
#+END_SRC
* Header files
#+BEGIN_SRC C :tangle qmckl.h
#include "qmckl_context.h"
#+END_SRC
* End of header
#+BEGIN_SRC C :tangle qmckl.h
#endif
#+END_SRC

View File

@ -1,10 +1,15 @@
# -*- mode: org -*- # -*- mode: org -*-
# vim: syntax=c
#+TITLE: Context #+TITLE: Context
This file is written in C because it is more natural to express the context in This file is written in C because it is more natural to express the context in
C than in Fortran. C than in Fortran.
#+BEGIN_SRC C :tangle qmckl_context.h
#ifndef QMCKL_CONTEXT_H
#define QMCKL_CONTEXT_H
#include "qmckl.h"
#+END_SRC
#+BEGIN_SRC C :tangle qmckl_context.c #+BEGIN_SRC C :tangle qmckl_context.c
#include <stdlib.h> /* malloc */ #include <stdlib.h> /* malloc */
@ -17,19 +22,15 @@ C than in Fortran.
is stored in the following data structure, which can't be seen is stored in the following data structure, which can't be seen
outside of the library. outside of the library.
#+BEGIN_SRC C :tangle qmckl_context.h #+BEGIN_SRC C :tangle qmckl_context.h
#define QMCKL_DEFAULT_PRECISION 53
#define QMCKL_DEFAULT_RANGE 2
/* 64-bit integer */ /* 64-bit integer */
typedef long long int qmckl_context ; typedef long long int qmckl_context ;
#+END_SRC #+END_SRC
#+BEGIN_SRC C :tangle qmckl_context.c #+BEGIN_SRC C :tangle qmckl_context.c
typedef struct qmckl_context_struct_ { typedef struct qmckl_context_struct {
struct qmckl_context_struct_ * prev; struct qmckl_context_struct * prev;
int precision; int precision;
int range; int range;
} qmckl_context_struct; } qmckl_context_struct;
@ -121,8 +122,53 @@ int qmckl_context_destroy(qmckl_context context) {
The following functions set and get the expected required precision The following functions set and get the expected required precision
and range. =precision= should be an integer between 2 and 53, and and range. =precision= should be an integer between 2 and 53, and
=range= should be an integer between 2 and 11. =range= should be an integer between 2 and 11.
The setter functions functions return a new context as a 64-bit integer. The setter functions functions return a new context as a 64-bit integer.
The getter functions return the value, as a 32-bit integer. The getter functions return the value, as a 32-bit integer.
The update functions return =QMCKL_SUCCESS= or =QMCKL_FAILURE=.
** =qmckl_context_update_precision=
#+BEGIN_SRC C :tangle qmckl_context.h
qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, int precision);
#+END_SRC
#+BEGIN_SRC C :tangle qmckl_context.c
qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, int precision) {
qmckl_context_struct* ctx;
if (precision < 2) return QMCKL_FAILURE;
if (precision > 53) return QMCKL_FAILURE;
ctx = (qmckl_context_struct*) context;
if (ctx == NULL) return QMCKL_FAILURE;
ctx->precision = precision;
return QMCKL_SUCCESS;
}
#+END_SRC
** =qmckl_context_update_range=
#+BEGIN_SRC C :tangle qmckl_context.h
qmckl_exit_code qmckl_context_update_range(const qmckl_context context, int range);
#+END_SRC
#+BEGIN_SRC C :tangle qmckl_context.c
qmckl_exit_code qmckl_context_update_range(const qmckl_context context, int range) {
qmckl_context_struct* ctx;
if (range < 2) return QMCKL_FAILURE;
if (range > 11) return QMCKL_FAILURE;
ctx = (qmckl_context_struct*) context;
if (ctx == NULL) return QMCKL_FAILURE;
ctx->range = range;
return QMCKL_SUCCESS;
}
#+END_SRC
** =qmckl_context_set_precision= ** =qmckl_context_set_precision=
@ -131,15 +177,15 @@ qmckl_context qmckl_context_set_precision(const qmckl_context context, int preci
#+END_SRC #+END_SRC
#+BEGIN_SRC C :tangle qmckl_context.c #+BEGIN_SRC C :tangle qmckl_context.c
qmckl_context qmckl_context_set_precision(const qmckl_context context, int precision) { qmckl_context qmckl_context_set_precision(const qmckl_context context, const int precision) {
qmckl_context_struct* ctx; qmckl_context new_context;
if (precision < 2) return (qmckl_context) 0; new_context = qmckl_context_copy(context);
if (precision > 53) return (qmckl_context) 0; if (new_context == 0) return 0;
ctx = (qmckl_context_struct*) qmckl_context_copy(context); if (qmckl_context_update_precision(context, precision) == QMCKL_FAILURE) return 0;
ctx->precision = precision;
return (qmckl_context) ctx; return new_context;
} }
#+END_SRC #+END_SRC
@ -150,14 +196,14 @@ qmckl_context qmckl_context_set_range(const qmckl_context context, int range);
#+BEGIN_SRC C :tangle qmckl_context.c #+BEGIN_SRC C :tangle qmckl_context.c
qmckl_context qmckl_context_set_range(const qmckl_context context, int range) { qmckl_context qmckl_context_set_range(const qmckl_context context, int range) {
qmckl_context_struct* ctx; qmckl_context new_context;
if (range < 2) return (qmckl_context) 0; new_context = qmckl_context_copy(context);
if (range > 11) return (qmckl_context) 0; if (new_context == 0) return 0;
ctx = (qmckl_context_struct*) qmckl_context_copy(context); if (qmckl_context_update_range(context, range) == QMCKL_FAILURE) return 0;
ctx->range = range;
return (qmckl_context) ctx; return new_context;
} }
#+END_SRC #+END_SRC
@ -191,3 +237,11 @@ int qmckl_context_get_range(const qmckl_context context) {
} }
#+END_SRC #+END_SRC
* End of header
#+BEGIN_SRC C :tangle qmckl_context.h
#endif
#+END_SRC