1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-11-19 12:32:40 +01:00
qmckl/tools/Building.org

407 lines
9.2 KiB
Org Mode
Raw Normal View History

2021-03-09 01:16:23 +01:00
#+TITLE: Building tools
This file contains all the tools needed to build the QMCkl library.
* Helper functions
#+NAME: header
#+begin_src sh :tangle no :exports none :output none
echo "This file was created by tools/Building.org"
#+end_src
#+NAME: check-src
#+begin_src bash
if [[ $(basename $PWD) != "src" ]] ; then
echo "This script needs to be run in the src directory"
exit -1
fi
#+end_src
#+NAME: url-issues
: https://github.com/trex-coe/qmckl/issues
#+NAME: url-web
: https://trex-coe.github.io/qmckl
#+NAME: license
#+begin_example
BSD 3-Clause License
Copyright (c) 2020, TREX Center of Excellence
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#+end_example
* Makefile
:PROPERTIES:
:header-args: :tangle ../src/Makefile :noweb yes :comments org
:END:
This is the main Makefile invoked by the ~make~ command.
The Makefile compiling the library is =Makefile.generated=, and is
generated by the script detailed in the next section.
** Header :noexport:
#+begin_src makefile
# <<header()>>
#+end_src
** Variables
#+begin_src makefile
QMCKL_ROOT=$(shell dirname $(CURDIR))
export CC CFLAGS FC FFLAGS LIBS QMCKL_ROOT
ORG_SOURCE_FILES=$(wildcard *.org)
OBJECT_FILES=$(filter-out $(EXCLUDED_OBJECTS), $(patsubst %.org,%.o,$(ORG_SOURCE_FILES)))
INCLUDE=-I$(QMCKL_ROOT)/include/
#+end_src
** Compiler options
GNU, Intel and LLVM compilers are supported. Choose here:
#+begin_src makefile
COMPILER=GNU
#COMPILER=INTEL
#COMPILER=LLVM
#+end_src
*** GNU
#+begin_src makefile
ifeq ($(COMPILER),GNU)
#----------------------------------------------------------
CC=gcc -g
CFLAGS=-fPIC $(INCLUDE) \
-fexceptions -Wall -Werror -Wpedantic -Wextra -fmax-errors=3
FC=gfortran -g
FFLAGS=-fPIC $(INCLUDE) \
-fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising \
-Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation \
-Wreal-q-constant -Wuninitialized -fbacktrace -finit-real=nan \
-ffpe-trap=zero,overflow,underflow
LIBS=-lgfortran -lm
#----------------------------------------------------------
endif
#+end_src
*** Intel
#+begin_src makefile
ifeq ($(COMPILER),INTEL)
#----------------------------------------------------------
CC=icc -xHost
CFLAGS=-fPIC -g -O2 $(INCLUDE)
FC=ifort -xHost
FFLAGS=-fPIC -g -O2 $(INCLUDE)
LIBS=-lm -lifcore -lirc
#----------------------------------------------------------
CC=icc -xHost
endif
#+end_src
*** LLVM
#+begin_src makefile
ifeq ($(COMPILER),LLVM)
#----------------------------------------------------------
CC=clang
CFLAGS=-fPIC -g -O2 $(INCLUDE)
FC=flang
FFLAGS=fPIC -g -O2 $(INCLUDE)
LIBS=-lm
#----------------------------------------------------------
endif
#+end_src
** Rules
The source files are created during the generation of the file ~Makefile.generated~.
#+begin_src makefile
.PHONY: clean
.SECONDARY: # Needed to keep the produced C and Fortran files
libqmckl.so: Makefile.generated
$(MAKE) -f Makefile.generated
test: Makefile.generated
$(MAKE) -f Makefile.generated test
doc: $(ORG_SOURCE_FILES)
$(QMCKL_ROOT)/tools/create_doc.sh
clean:
$(RM) qmckl.h test_qmckl_* test_qmckl.c test_qmckl \
qmckl_*.f90 qmckl_*.c qmckl_*.o qmckl_*.h \
Makefile.generated libqmckl.so *.html *.mod
Makefile.generated: Makefile $(QMCKL_ROOT)/tools/create_makefile.sh $(ORG_SOURCE_FILES)
$(QMCKL_ROOT)/tools/create_makefile.sh
#+end_src
* Script to tangle the org-mode files
:PROPERTIES:
:header-args: :tangle tangle.sh :noweb yes :shebang #!/bin/bash :comments org
:END:
#+begin_src bash
# <<header()>>
<<check_src>>
#+end_src
This file needs to be run from the QMCKL =src= directory.
It tangles all the files in the directory. It uses the
=config_tangle.el= file, which contains information required to
compute the current file names using for example ~(eval c)~ to get
the name of the produced C file.
The file is not tangled if the last modification date of the org
file is less recent than one of the tangled files.
#+begin_src bash
function tangle()
{
if [[ -f ${1%.org}.c && $1 -ot ${1%.org}.c ]]
then return
elif [[ -f ${1%.org}.f90 && $1 -ot ${1%.org}.f90 ]]
then return
fi
emacs --batch $1 --load=../tools/config_tangle.el -f org-babel-tangle
}
for i in $@
do
echo "--- $i ----"
tangle $i
done
#+end_src
* Script to generate auto-generated Makefile
:PROPERTIES:
:header-args: :tangle create_makefile.sh :noweb yes :shebang #!/bin/bash :comments org
:END:
This script generates the Makefile that compiles the library.
The ~OUTPUT~ variable contains the name of the generated Makefile,typically
=Makefile.generated=.
#+begin_src bash
# <<header()>>
<<check_src>>
OUTPUT=Makefile.generated
#+end_src
We start by tangling all the org-mode files.
#+begin_src bash
${QMCKL_ROOT}/tools/tangle.sh *.org
#+end_src
Then we create the list of ~*.o~ files to be created, for library
functions:
#+begin_src bash
OBJECTS=""
for i in $(ls qmckl_*.c) ; do
FILE=${i%.c}
OBJECTS="${OBJECTS} ${FILE}.o"
done >> $OUTPUT
for i in $(ls qmckl_*_f.f90) ; do
FILE=${i%.f90}
OBJECTS="${OBJECTS} ${FILE}.o"
done >> $OUTPUT
#+end_src
for tests in C:
#+begin_src bash
TESTS=""
for i in $(ls test_qmckl_*.c) ; do
FILE=${i%.c}.o
TESTS="${TESTS} ${FILE}"
done >> $OUTPUT
#+end_src
and for tests in Fortran:
#+begin_src bash
TESTS_F=""
for i in $(ls test_qmckl_*_f.f90) ; do
FILE=${i%.f90}.o
TESTS_F="${TESTS_F} ${FILE}"
done >> $OUTPUT
#+end_src
Finally, we append the rules to the Makefile
#+begin_src bash
cat << EOF > ${OUTPUT}
CC=$CC
CFLAGS=$CFLAGS -I../munit/
FC=$FC
FFLAGS=$FFLAGS
OBJECT_FILES=$OBJECTS
TESTS=$TESTS
TESTS_F=$TESTS_F
LIBS=$LIBS
libqmckl.so: \$(OBJECT_FILES)
\$(CC) -shared \$(OBJECT_FILES) -o libqmckl.so
%.o: %.c
\$(CC) \$(CFLAGS) -c \$*.c -o \$*.o
qmckl_f.o: ../include/qmckl_f.f90
\$(FC) \$(FFLAGS) -c ../include/qmckl_f.f90 -o qmckl_f.o
%.o: %.f90 qmckl_f.o
\$(FC) \$(FFLAGS) -c \$*.f90 -o \$*.o
test_qmckl: test_qmckl.c libqmckl.so \$(TESTS) \$(TESTS_F)
\$(CC) \$(CFLAGS) -Wl,-rpath,$PWD -L. \
../munit/munit.c \$(TESTS) \$(TESTS_F) -lqmckl \$(LIBS) test_qmckl.c -o test_qmckl
test: test_qmckl
./test_qmckl
.PHONY: test
EOF
#+end_src
* Script to build the final qmckl.h file
:PROPERTIES:
:header-args:bash: :tangle build_qmckl_h.sh :noweb yes :shebang #!/bin/bash :comments org
:END:
#+begin_src bash :noweb yes
# <<header()>>
#+end_src
#+NAME: qmckl-header
#+begin_src text :noweb yes
------------------------------------------
QMCkl - Quantum Monte Carlo kernel library
------------------------------------------
Documentation : <<url-web()>>
Issues : <<url-issues()>>
<<license()>>
#+end_src
All the produced header files are concatenated in the =qmckl.h=
file, located in the include directory. The =*_private.h= files
are excluded.
Put =.h= files in the correct order:
#+begin_src bash
HEADERS=""
for i in $(cat table_of_contents)
do
HEADERS+="${i%.org}.h "
done
#+end_src
Generate C header file
#+begin_src bash
OUTPUT="../include/qmckl.h"
cat << EOF > ${OUTPUT}
/*
,* <<qmckl-header>>
,*/
#ifndef __QMCKL_H__
#define __QMCKL_H__
#include <stdlib.h>
#include <stdint.h>
EOF
for i in ${HEADERS}
do
if [[ -f $i ]] ; then
cat $i >> ${OUTPUT}
fi
done
cat << EOF >> ${OUTPUT}
#endif
EOF
#+end_src
Generate Fortran interface file from all =qmckl_*_fh.f90= files
#+begin_src bash
HEADERS="qmckl_*_fh.f90"
OUTPUT="../include/qmckl_f.f90"
cat << EOF > ${OUTPUT}
!
! <<qmckl-header>>
!
module qmckl
use, intrinsic :: iso_c_binding
EOF
for i in ${HEADERS}
do
cat $i >> ${OUTPUT}
done
cat << EOF >> ${OUTPUT}
end module qmckl
EOF
#+end_src
* Script to build the documentation
* Script to build the documentation