1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-12-22 12:23:56 +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
*.c
*.h
*~
*.so
Makefile.generated

View File

@ -1,30 +1,24 @@
CC=gcc
CFLAGS=-fexceptions -Wall -Werror -Wpedantic -Wextra
CFLAGS=-fPIC -fexceptions -Wall -Werror -Wpedantic -Wextra
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
ORG_SOURCE_FILES=qmckl_context.org
OBJECT_FILES=$(patsubst %.org,%.o,$(ORG_SOURCE_FILES))
export CC CFLAGS FC FFLAGS
.PHONY: clean
ORG_SOURCE_FILES=$(wildcard qmckl*.org)
OBJECT_FILES=$(filter-out $(EXCLUDED_OBJECTS), $(patsubst %.org,%.o,$(ORG_SOURCE_FILES)))
all: $(OBJECT_FILES)
.PHONY: clean
.SECONDARY: # Needed to keep the produced C and Fortran files
%.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
libqmckl.so: Makefile.generated
$(MAKE) -f Makefile.generated
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

@ -8,27 +8,31 @@
comments and LaTex formulas close to the code. There exists multiple
possibilities to convert org-mode files into different formats such as
HTML or pdf.
For a tutorial on literate programming with org-mode, follow
For a tutorial on literate programming with org-mode, follow
[[http://www.howardism.org/Technical/Emacs/literate-programming-tutorial.html][this link]].
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.
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
Any text editor can be used to edit org-mode files. For a better
user experience Emacs is recommended.
For users hating Emacs, it is good to know that Emacs can behave
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
script can convert jupyter notebooks to org-mode files:
#+BEGIN_SRC sh tangle: nb_to_org.sh
#!/bin/bash
# $ nb_to_org.sh notebook.ipynb
# produces the org-mode file notebook.org
# $ nb_to_org.sh notebook.ipynb
# produces the org-mode file notebook.org
set -e
@ -45,7 +49,7 @@ rm ${nb}.md
The Fortran source files should provide a C interface using
iso-c-binding. The name of the Fortran source files should end
with =_f.f90= to be properly handled by the Makefile.
** Documentation
- [[qmckl_context.org][Context]]

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