Skip to content

Instantly share code, notes, and snippets.

@Sharpie
Created February 1, 2012 21:56
Show Gist options
  • Save Sharpie/1719727 to your computer and use it in GitHub Desktop.
Save Sharpie/1719727 to your computer and use it in GitHub Desktop.
Handout on using makefiles to compile Fortran source code
module integration_subs
interface
subroutine trap_integrator(f, ll, ul, n, ans)
use types
real(dp), intent(in):: ll, ul
real(dp), intent(out):: ans
integer, intent(in):: n
interface
function f(x)
use types
real(dp), intent(in):: x
real(dp):: f
end function f
end interface
end subroutine trap_integrator
end interface
end module integration_subs
subroutine trap_integrator(f, ll, ul, n, ans)
use types
implicit none
real(dp), intent(in):: ll, ul
real(dp), intent(out):: ans
integer, intent(in):: n
interface
function f(x)
use types
real(dp), intent(in):: x
real(dp):: f
end function f
end interface
real(dp):: h
integer:: i
h = (ul - ll) / n
ans = (f(ll) + f(ul)) / 2
do i = 1, n - 1
ans = ans + f(ll + i * h)
end do
ans = h * ans
end subroutine trap_integrator
Written in 2012 by Charlie Sharpsteen
All files contained in this directory I hereby place in the public domain to
the extent governable by law, unless noted otherwise. Explicitly, the files are
released under the terms of CC0:
http://creativecommons.org/publicdomain/zero/1.0
LDFLAGS = -L$(HOME)/lib
LDFLAGS += -lfintegrate
FCFLAGS = -Wall -fbounds-check
FCFLAGS += -J$(HOME)/modules
pipe_flow: pipe_main.f90
gfortran $(FCFLAGS) $^ -o $@ $(LDFLAGS)
LDFLAGS =
LDFLAGS +=
FCFLAGS = -Wall -fbounds-check
FCFLAGS +=
pipe_flow: pipe_main.f90 integration_subs.o types.o
gfortran $(FCFLAGS) $^ -o $@ $(LDFLAGS)
integration_subs.o: integration_subs.f90 types.o
# `$<' is shorthand for the first dependency
# in the list. This is used instead of `$^'
# because only the `.f90' file needs to
# be compiled.
gfortran $(FCFLAGS) -c $<
types.o: types.f90
gfortran $(FCFLAGS) -c $<
LDFLAGS =
LDFLAGS +=
FCFLAGS = -Wall -fbounds-check
FCFLAGS +=
pipe_flow: types.f90 integration_subs.f90 pipe_main.f90
gfortran $(FCFLAGS) $^ -o $@ $(LDFLAGS)
LDFLAGS =
LDFLAGS +=
FCFLAGS = -Wall -fbounds-check
FCFLAGS +=
pipe_flow: pipe_flow.f90
gfortran $(FCFLAGS) $^ -o $@ $(LDFLAGS)
# All make commands are saved into a file named
# Makefile that is saved next to the project
# source code.
#
# Makefile comments start with a hash sign: `#'
#
# Variables may be assigned values for quick
# reference later. Values are retireved from
# variables by wrapping the variable
# name inside `$()'.
LDFLAGS = <library search directories go here>
# The append operator `+=' is shorthand for
# VAR = $(VAR) <stuff to append>
LDFLAGS += <library names go here>
FCFLAGS = <gfortran compiler flags go here>
FCFLAGS += <module search directories go here>
# A "make target" is a file, such as an executable
# program. The shell commands required to build
# the target follow in a _tab indented_ list.
<target name>: <list of files or target names>
# `$@' is shorthand for the target name
# and `$^' is shorthand for the list of
# dependencies.
gfortran $(FCFLAGS) $^ -o $@ $(LDFLAGS)
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
\documentclass[10pt]{article}
\usepackage[letterpaper,margin=0.25in]{geometry}
% Better Serif font for body text
\usepackage[osf]{mathpazo}
% Bettery typewriter font for code examples
\usepackage{inconsolata}
% Define a command for typesetting tab keys
\newcommand{\tabkey}{\fbox{\scshape Tab$\rightarrow$}\hspace{1ex}}
% Style definitions for pretty-printing source code
\usepackage{tikzCodeBlock}
\lstdefinestyle{maketemplate}{
language = make,
basicstyle=\ttfamily\footnotesize,
commentstyle=\color{gray},
% Emphasize any text surrounded by brackets
moredelim=[s][\sffamily\itshape]
{<}
{>},
upquote = false,
showtabs = true,
tab = \tabkey
}
\lstdefinestyle{makefile}{
language = make,
basicstyle=\ttfamily\footnotesize,
commentstyle=\color{gray},
upquote = false,
showtabs = true,
tab = \tabkey
}
\tikzset{
/tikzCode/defaults/code body/.append style={
draw = gray,
codebody color = white },
/tikzCode/defaults/code title outline/.append style={draw=gray}
}
\pagestyle{empty}
\begin{document}
\begin{center}
{\Large\scshape Makefiles}\\[-0.75\baselineskip]\rule{5em}{0.4pt}
\end{center}
\noindent
Make is a common tool used by programmers to automate tasks such as compiling
code. Make is configured by writing down a set of rules that specify how target
files are to be built from lists of dependencies. The rules are stored inside a
\verb|Makefile| that lives next to the program source code. This file is then
processed by the \verb|make| shell command. A basic Makefile provides two
important benefits: a productivity boost by eliminating the need to re-type
complicated commands and protection from typos that can cause critical files to
be overwritten. As projects grow more complicated, Makefiles provide additional
benefits by ensuring components are assembled in the correct order and that no
file is re-compiled unless the file has been modified more recently than a
target that depends on it.
\bigskip\noindent
A simple template for a Makefile has the following form:
\begin{center}
\begin{minipage}{0.45\textwidth}
\tikzCodeInput[title={Makefile Template},listing style=maketemplate]{Makefile.template}
\end{minipage}
\end{center}
\begin{minipage}{0.45\textwidth}
\tikzCodeInput[title={Simple Makefile},listing style=makefile]{Makefile.simple}
\end{minipage}
\hspace{0.02\textwidth}
\begin{minipage}{0.48\textwidth}
\tikzCodeInput[title={Makefile with Multiple Source Files},listing style=makefile]{Makefile.multiple}
\end{minipage}
\begin{minipage}{0.45\textwidth}
\tikzCodeInput[title={Makefile with Module Targets},listing style=makefile]{Makefile.modules}
\end{minipage}
\hspace{0.05\textwidth}
\begin{minipage}{0.45\textwidth}
\tikzCodeInput[title={Makefile with External Libraries},listing style=makefile]{Makefile.libs}
\end{minipage}
\end{document}
module types
integer, parameter:: dp = selected_real_kind(15)
end module types
program pipe_flow
use types
implicit none
real(dp):: ll = 0._dp, ul = 3._dp, ans
integer:: n
interface
subroutine trap_integrator(f, ll, ul, n, ans)
use types
real(dp), intent(in):: ll, ul
real(dp), intent(out):: ans
integer, intent(in):: n
interface
function f(x)
use types
real(dp), intent(in):: x
real(dp):: f
end function f
end interface
end subroutine trap_integrator
function q(r)
use types
real(dp), intent(in):: r
real(dp):: q
end function q
end interface
! Get input
write(*, '(A)', advance = 'no') "Enter number of divisions: "
read(*, *) n
! Call integration routine
call trap_integrator(q, ll, ul, n, ans)
! Write output
write(*,"(A,I3,A,F7.3)") "Estimated flow rate, using ", n, " iterations: ", ans
stop
end program pipe_flow
subroutine trap_integrator(f, ll, ul, n, ans)
use types
implicit none
real(dp), intent(in):: ll, ul
real(dp), intent(out):: ans
integer, intent(in):: n
interface
function f(x)
use types
real(dp), intent(in):: x
real(dp):: f
end function f
end interface
real(dp):: h
integer:: i
h = (ul - ll) / n
ans = (f(ll) + f(ul)) / 2
do i = 1, n - 1
ans = ans + f(ll + i * h)
end do
ans = h * ans
end subroutine trap_integrator
function q(r)
use types
implicit none
real(dp):: r
real(dp):: q
real(dp), parameter:: PI = 3.14159, rp = 3._dp/12
r = r / 12
q = 6 * PI * (1 - r / rp)**(1._dp/7._dp) * r
end function q
program pipe_flow
use types
use integration_subs
implicit none
real(dp):: ll = 0._dp, ul = 3._dp, ans
integer:: n
interface
function q(r)
use types
real(dp), intent(in):: r
real(dp):: q
end function q
end interface
! Get input
write(*, '(A)', advance = 'no') "Enter number of divisions: "
read(*, *) n
! Call integration routine
call trap_integrator(q, ll, ul, n, ans)
! Write output
write(*,"(A,I3,A,F7.3)") "Estimated flow rate, using ", n, " iterations: ", ans
stop
end program pipe_flow
function q(r)
use types
implicit none
real(dp):: r
real(dp):: q
real(dp), parameter:: PI = 3.14159, rp = 3._dp/12
r = r / 12
q = 6 * PI * (1 - r / rp)**(1._dp/7._dp) * r
end function q
% Copyright (c) 2009-2012 by Charlie Sharpsteen
% Some rights reserved.
%
% Redistribution and use in source and binary forms of the software as well
% as documentation, with or without modification, are permitted provided
% that the following conditions are met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
%
% * 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.
%
% * The names of the contributors may not be used to endorse or
% promote products derived from this software without specific
% prior written permission.
%
% THIS SOFTWARE AND DOCUMENTATION 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 OWNER
% 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 AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
% DAMAGE.
% =============================================================================
%
% tikzCodeBlock.sty
%
% =============================================================================
% A nicely styled container for multipage code listings. Look and feel inspired
% by SyntaxHighlighter (although this is just a pale imitation):
%
% http://alexgorbatchev.com/SyntaxHighlighter
%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tikzCodeBlock}[2012/01/20 v0.2 Multipage listings set inside TikZ nodes]
\RequirePackage{tikz}
\usetikzlibrary{positioning}
\RequirePackage{framed}
\RequirePackage{listings}
% We start off defining a new node shape to hold our code chunks.
% It has a couple of extra options when it comes to background color
% and such.
% Shape 'code node'
%
% Inherits everything from rectangle except the behind background path.
%
% Adapted from Texample:
% http://www.texample.net/tikz/examples/rectangle-node-with-diagonal-fill/
%
% Contributed by Mark Wibrow- the guy who designed the PGF math engine
% and made most of the stock node shapes.
%
\pgfdeclareshape{code node}
{
% This bit from \pgflibarayshapes.code.tex
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
\inheritbackgroundpath[from=rectangle]
\inheritbeforebackgroundpath[from=rectangle]
\inheritbehindforegroundpath[from=rectangle]
\inheritforegroundpath[from=rectangle]
\inheritbeforeforegroundpath[from=rectangle]
% Now do the background filling.
\behindbackgroundpath{%
% \southwest and \northeast defined by rectangle, but
% (somewhat annoyingly) not \southeast and \northwest
% so use this workaround.
\pgfextractx{\pgf@xa}{\southwest}%
\pgfextracty{\pgf@ya}{\southwest}%
\pgfextractx{\pgf@xb}{\northeast}%
\pgfextracty{\pgf@yb}{\northeast}%
% New code here. We want to draw a bar 4 ex wide to lie
% under the line numbers. So we define two points that
% are 7 ex to the left of the southwest and northwest corners.
\def\pgf@numberstripe@southwest{%
\pgfpointadd{\southwest}%
{\pgfpoint{\pgf@codestripe@width}{0}}%
}
\def\pgf@numberstripe@northwest{%
\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@yb}}%
{\pgfpoint{\pgf@codestripe@width}{0}}%
}
% Now we draw the code bar.
\pgfpathmoveto{\southwest}%
\pgfpathlineto{\pgf@numberstripe@southwest}%
\pgfpathlineto{\pgf@numberstripe@northwest}%
\pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}%
\pgfpathclose
% Now fill it with a nice light grey.
\color{\pgf@codestripe@color}%
\pgfusepath{fill}%
% Now for the rest of the node.
\pgfpathmoveto{\pgf@numberstripe@southwest}%
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}%
\pgfpathlineto{\northeast}%
\pgfpathlineto{\pgf@numberstripe@northwest}%
\pgfpathclose
%
\color{\pgf@codebody@color}%
\pgfusepath{fill}
}
}
%--------------------- Begin User Level Shape Options -----------------
% Default widths.
\def\pgf@codestripe@width{0pt}
% Default color values
\def\pgf@codebody@color{white}
\def\pgf@codestripe@color{gray!30}
% Use these with PGF
\def\pgfsetcodestripecolor#1{\def\pgf@codestripe@color{#1}}%
\def\pgfsetcodestripewidth#1{\def\pgf@codestripe@width{#1}}%
\def\pgfsetcodebodycolor#1{\def\pgf@codebody@color{#1}}%
% Use these with TikZ
\tikzoption{codestripe color}{\pgfsetcodestripecolor{#1}}
\tikzoption{codestripe width}{\pgfsetcodestripewidth{#1}}
\tikzoption{codebody color}{\pgfsetcodebodycolor{#1}}
%--------------------- End User Level Shape Options -------------------
%===============================================
%--------------------- Begin Internal Package Macros ------------------
\newcommand\tikzCode@setupKeys{%
% This command leverages the pgfkeys package,
% included by tikz, to set up handling for options
% of the form [key=value]
\pgfkeys{/tikzCode/title/.store in=\tikzCode@codeNodeTitle,
/tikzCode/footer/.store in=\tikzCode@codeNodeFooter,
/tikzCode/listing style/.store in=\tikzCode@listingStyle,
/tikzCode/code body/.style={/tikzCode/defaults/code body},
/tikzCode/code title body/.style={/tikzCode/defaults/code title body},
/tikzCode/code title outline/.style={/tikzCode/defaults/code title outline},
/tikzCode/code footer/.style={/tikzCode/defaults/code footer},
}
}
% This macro sets a chunk of text inside a specialized node.
\newcommand{\tikzCode@place@codenodebody}[1]{%
\node[/tikzCode/code body] (code node body) {#1};
}
% This macro adds a header.
\newcommand{\tikzCode@place@codenodetitle}{%
\node[/tikzCode/code title body] (code node title) {\tikzCode@codeNodeTitle};
\draw[/tikzCode/code title outline] (code node title.south west) --
(code node title.south east) --
(code node title.north east) --
(code node title.north west) --
cycle;
}
% And this one adds a footer.
\newcommand{\tikzCode@place@codenodefooter}{%
\node[/tikzCode/code footer] {\tikzCode@codeNodeFooter};
}
% This macro outputs a singleton frame.
\newcommand{\tikzCode@place@singleframe}[1]{%
\begin{tikzpicture}%
\tikzCode@place@codenodebody{#1}
\ifx \tikzCode@codeNodeTitle \undefined
% Nothin' to do.
\relax
\else
\tikzCode@place@codenodetitle
\fi
\ifx \tikzCode@codeNodeFooter \undefined
\relax
\else
\tikzCode@place@codenodefooter
\fi
\end{tikzpicture}%
}
% This macro outputs the first of a series of frames.
\newcommand{\tikzCode@place@firstframe}[1]{%
\begin{tikzpicture}%
\tikzCode@place@codenodebody{#1}
\ifx \tikzCode@codeNodeTitle \undefined
% Nothin' to do.
\relax
\else
\tikzCode@place@codenodetitle
\fi
\end{tikzpicture}%
}
% This macro outputs the middle portions of a series of frames.
\newcommand{\tikzCode@place@middleframe}[1]{%
\begin{tikzpicture}%
\tikzCode@place@codenodebody{#1}
\end{tikzpicture}%
}
% This macro outputs the last of a series of frames.
\newcommand{\tikzCode@place@lastframe}[1]{%
\begin{tikzpicture}%
\tikzCode@place@codenodebody{#1}
\ifx \tikzCode@codeNodeFooter \undefined
\relax
\else
\tikzCode@place@codenodefooter
\fi
\end{tikzpicture}%
}
% This macro patches our code into the framed package.
\newcommand{\tikzCode@set@framedcommands}{%
\def\FrameCommand{\tikzCode@place@singleframe}%
\def\FirstFrameCommand{\tikzCode@place@firstframe}%
\def\MidFrameCommand{\tikzCode@place@middleframe}%
\def\LastFrameCommand{\tikzCode@place@lastframe}%
}
%--------------------- End Internal Package Macros -----------------------
% Default Code Node Style definitions.
\tikzset{
/tikzCode/defaults/code body/.style={
% The code node is a homebrewed shape- several things can
% possibly go pear shaped with it- for example, adding rounded
% corners causes things to go whacky. Also- don't use the fill
% command :P
shape = code node,
draw = blue!50,
thick,
codebody color = blue!10,
outer sep = 0pt,
inner sep = 1ex,
% Subtract off 2 * inner sep and line width
text width = {\linewidth - 2ex - 1.6pt}
},
/tikzCode/defaults/code title body/.style={
fill = white,
inner sep = 1ex,
outer sep = 0pt,
right = 0pt of code node body.north west,
anchor = base west
},
/tikzCode/defaults/code title outline/.style={
draw = blue!50,
thick
},
/tikzCode/defaults/code footer/.style={
draw = blue!50,
thick,
fill = white,
inner sep = 1ex,
outer sep = 0pt,
above = 0pt of code node body.south,
anchor = base
}
}
% -----------------------------------------------------------------------------
% User-Level Commands
% -----------------------------------------------------------------------------
% tikzCodeBlock
% =============
% This environment captures contents verbatim, processes the text with the
% listings package, pagebreaks the results into chunks using the framed
% package, then sets each chunk in a TikZ node.
%
% Defined using `\lstnewenvironment` so that the listings package knows when to
% stop capturing input verbatim.
\lstnewenvironment{tikzCodeBlock}[1][]{%
% Process environment options.
\tikzCode@setupKeys
% Shift the key directory to our namespace.
\pgfkeys{ /tikzCode/.cd, #1 }%
\ifx \tikzCode@listingStyle \undefined
\lstset{resetmargins = true}%
\else
\lstset{style = \tikzCode@listingStyle, resetmargins = true}%
\fi
% Start the framed environment.
\tikzCode@set@framedcommands
\MakeFramed{\FrameRestore}%
}%
{\endMakeFramed}
% tikzCodeInput
% =============
% This is like the tikzCodeBlock environment except that it reads input from a
% file.
\newcommand{\tikzCodeInput}[2][]{%
% Process environment options.
\tikzCode@setupKeys
% Shift the key directory to our namespace.
\pgfkeys{ /tikzCode/.cd, #1 }%
\tikzCode@set@framedcommands
% Start the framed environment.
\MakeFramed{\FrameRestore}%
\ifx \tikzCode@listingStyle \undefined
\lstinputlisting[resetmargins = true]{#2}%
\else
\lstinputlisting[style = \tikzCode@listingStyle, resetmargins = true]{#2}%
\fi
\endMakeFramed
}
% Make sure LaTeX knows we're done here.
\endinput
module types
integer, parameter:: dp = selected_real_kind(15)
end module types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment