aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2022-11-23 16:09:08 +0100
committerAnton Khirnov <anton@khirnov.net>2024-04-15 13:34:54 +0200
commit098523b825c14184592a8717c2c3becbf6bc3f9f (patch)
tree691cce5484bb2a63555e688a5bfad8fda7585e70
parent1bf2694303843192e7098876c0fc709307eece65 (diff)
Switch from meson to configure+make.
Meson is an extra dependency and generally sucks.
-rw-r--r--Makefile72
-rw-r--r--README9
-rwxr-xr-xconfigure154
-rw-r--r--cpu.c4
-rw-r--r--ell_grid_solve.c4
-rw-r--r--meson.build104
-rw-r--r--meson_options.txt1
-rw-r--r--residual_calc.c6
-rw-r--r--transfer.c6
9 files changed, 241 insertions, 119 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1991773
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,72 @@
+MAKEFLAGS += --no-builtin-rules
+
+include config.mak
+
+TARGET = libmg2d.so
+
+TESTPROGS = $(addsuffix _test, \
+ relax \
+ relax_mpi \
+ mg2d \
+ mg2d_mpi \
+)
+
+VPATH = $(SOURCE_DIR)
+
+CFLAGS += -std=c11 -fPIC
+CFLAGS += -g -O3
+CFLAGS += -D_XOPEN_SOURCE=700 # POSIX
+CFLAGS += -D_DEFAULT_SOURCE=1 # for random_r
+CFLAGS += -I. -I$(SOURCE_DIR)
+CFLAGS += $(CFLAGS_DEP)
+
+LDFLAGS_COMMON = $(LDFLAGS_DEP)
+LDFLAGS_COMMON += -lm -llapacke -lblas -lthreadpool -lndarray
+LDFLAGS_TARGET = -shared -Wl,--version-script=$(SOURCE_DIR)/libmg2d.v
+
+OBJS = \
+ bicgstab.c.o \
+ boundary.c.o \
+ components.c.o \
+ cpu.c.o \
+ ell_grid_solve.c.o \
+ log.c.o \
+ mg2d.c.o \
+ residual_calc.c.o \
+ timer.c.o \
+ transfer.c.o
+
+OBJS-$(HAVE_NASM) = \
+ cpuid.asm.o \
+ ndarray.asm.o \
+ residual_calc.asm.o \
+ transfer_interp.asm.o \
+
+OBJS += $(OBJS-yes)
+
+all: $(TARGET)
+
+testprogs: $(TESTPROGS)
+
+$(TARGET) $(TESTPROGS): $(OBJS)
+ $(CC) -o $@ $(OBJS) $(TESTOBJ) $(LDFLAGS_COMMON) $(LDFLAGS)
+
+$(TARGET): LDFLAGS = $(LDFLAGS_TARGET)
+
+$(TESTPROGS): %: %.c.o
+$(TESTPROGS): $(TARGET)
+$(foreach testprog, $(TESTPROGS), $(eval $(testprog): TESTOBJ = $(testprog).c.o))
+
+%.c.o: %.c
+ $(CC) $(CFLAGS) -MMD -MF $(@:.o=.d) -MT $@ -c -o $@ $<
+
+%.asm.o: %.asm
+ nasm -i $(SOURCE_DIR)/ -f elf64 -MD $(@:.o=.d) -MT $@ $<
+ nasm -i $(SOURCE_DIR)/ -f elf64 -o $@ $<
+
+clean:
+ -rm -f *.o *.d *.pyc $(TARGET)
+
+-include $(OBJS:.o=.d)
+
+.PHONY: all testprogs clean
diff --git a/README b/README
index 6519e76..3209a07 100644
--- a/README
+++ b/README
@@ -15,16 +15,17 @@ via email).
Building and installation
=========================
-The library uses the meson build system. A C99-compliant compiler and a POSIX
-environment are expected.
-
-Dependencies:
+A C99-compliant compiler and a POSIX environment are expected, as well as the
+foloowing dependencies:
- BLAS
- LAPACKE (the C interface to LAPACK)
- libthreadpool (thread pool utility library)
- libndarray (array utility library)
- MPI
+You must create a separate build directory and run the 'configure' script from
+there, followed by 'make'.
+
The shared library and the headers mg2d.h, mg2d_boundary.h, mg2d_constants.h
must be copied to where the linker and C compiler, respectively, will find them
(typically /usr/local/lib and /usr/local/include).
diff --git a/configure b/configure
new file mode 100755
index 0000000..a2dfa88
--- /dev/null
+++ b/configure
@@ -0,0 +1,154 @@
+#!/bin/bash
+# mg2d configure script
+# partially inspired by/based on the FFmpeg configure script
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+bootstrap() {
+ local source_dir
+
+ [ -e configure ] && die "Cannot build from the source dir, create a separate build directory"
+
+ source_dir=$(realpath $(dirname "$0"))
+ [ -d "$source_dir" ] || die "Cannot locate source directory"
+
+ [ -h src ] || ln -s "$source_dir" src
+
+ [ -h Makefile ] || ln -s "$source_dir/Makefile"
+
+ echo $source_dir
+}
+
+toupper() {
+ echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
+}
+
+is_in() {
+ value=$1
+ shift
+ for var in $*; do
+ [ $var = $value ] && return 0
+ done
+ return 1
+}
+
+probe_arch() {
+ arch=$(cc -dumpmachine | sed 's/-.*//')
+}
+
+check_mpi() {
+ pkg-config --exists mpi || return 1
+ mpi_cflags=$(pkg-config --cflags mpi)
+ mpi_libs=$(pkg-config --libs mpi)
+}
+
+check_nasm() {
+ if ! command -v nasm &> /dev/null; then
+ echo "nasm not found, assembly code will not be built"
+ return 1
+ fi
+}
+
+check_component() {
+ name=$1
+ shift
+ eval "check_$name" $@ && eval "have_$name=yes"
+}
+
+source_dir=$(bootstrap)
+
+
+CMDLINE_SET="
+ cc
+"
+
+cc=cc
+
+for arg; do
+ name="${arg%%=*}"
+ name="${name#--}"
+ name=$(echo "$name" | sed 's/-/_/g')
+
+ val="${arg#*=}"
+
+ if is_in $name $CMDLINE_SET; then
+ eval $name='$val'
+ continue
+ fi
+
+ die "Unknown commandline argument: $name $val"
+done
+
+probe_arch
+
+COMPONENTS_REQUIRED="
+ mpi
+"
+
+COMPONENTS_OPTIONAL="
+ nasm
+"
+
+COMPONENTS="
+ $COMPONENTS_REQUIRED
+ $COMPONENTS_OPTIONAL
+"
+
+for c in $COMPONENTS_REQUIRED; do
+ check_component $c || die "Required component $c not found"
+done
+
+for c in $COMPONENTS_OPTIONAL; do
+ check_component $c
+done
+
+cat > config.mak <<EOF
+SOURCE_DIR = $source_dir
+CC = $cc
+CFLAGS_DEP = $mpi_cflags
+LDFLAGS_DEP = $mpi_libs
+EOF
+
+cat > config.h <<EOF
+#ifndef MG2D_CONFIG_H
+#define MG2D_CONFIG_H
+
+EOF
+
+cat > config.asm << EOF
+EOF
+
+case "$arch" in
+ x86_64)
+ echo "ARCH_X86_64 = 1" >> config.mak
+ echo "#define ARCH_X86_64 1" >> config.h
+ echo "%define ARCH_X86_64 1" >> config.asm
+ ;;
+ *)
+ echo "ARCH_X86_64 = 0" >> config.mak
+ echo "#define ARCH_X86_64 0" >> config.h
+ echo "%define ARCH_X86_64 0" >> config.asm
+ ;;
+esac
+
+for c in $COMPONENTS; do
+ C=$(toupper $c)
+ have_ref=have_$c
+
+ if [ -n "${!have_ref}" ]; then
+ val_mak=yes
+ val_c=1
+ else
+ val_mak=no
+ val_c=0
+ fi
+
+ echo "HAVE_$C = $val_mak" >> config.mak
+ echo "#define HAVE_$C $val_c" >> config.h
+
+done
+
+echo "#endif // MG2D_CONFIG_H" >> config.h
diff --git a/cpu.c b/cpu.c
index 58d9154..3dd2ae8 100644
--- a/cpu.c
+++ b/cpu.c
@@ -21,7 +21,7 @@
#include "cpu.h"
-#if ARCH_X86 && HAVE_EXTERNAL_ASM
+#if ARCH_X86_64 && HAVE_NASM
static int get_cpu_flags_x86(void)
{
int rval = 0;
@@ -161,7 +161,7 @@ int mg2di_cpu_flags_get(void)
{
int flags = 0;
-#if ARCH_X86 && HAVE_EXTERNAL_ASM
+#if ARCH_X86_64 && HAVE_NASM
flags = get_cpu_flags_x86();
#endif
diff --git a/ell_grid_solve.c b/ell_grid_solve.c
index dad8861..ecd9d8f 100644
--- a/ell_grid_solve.c
+++ b/ell_grid_solve.c
@@ -353,7 +353,7 @@ static void boundaries_apply(EGSContext *ctx, NDArray *a_dst, int init)
mg2di_timer_stop(&ctx->timer_bnd);
}
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
void mg2di_line_madd_fma3(ptrdiff_t linesize, double *dst, const double *src, double c);
#endif
@@ -980,7 +980,7 @@ int mg2di_egs_init(EGSContext *ctx, int flags)
priv->r.relax_factor *= r->relax_multiplier;
priv->r.line_add = line_madd_c;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
if (ctx->cpuflags & MG2DI_CPU_FLAG_FMA3)
priv->r.line_add = mg2di_line_madd_fma3;
#endif
diff --git a/meson.build b/meson.build
deleted file mode 100644
index 3134837..0000000
--- a/meson.build
+++ /dev/null
@@ -1,104 +0,0 @@
-project('libmg2d', 'c',
- default_options : ['c_std=c11'])
-
-add_project_arguments('-D_XOPEN_SOURCE=700', language : 'c')
-
-lib_src = [
- 'bicgstab.c',
- 'boundary.c',
- 'components.c',
- 'cpu.c',
- 'ell_grid_solve.c',
- 'log.c',
- 'mg2d.c',
- 'residual_calc.c',
- 'timer.c',
- 'transfer.c',
-]
-lib_obj = []
-
-verscript = 'libmg2d.v'
-ver_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), verscript)
-
-cc = meson.get_compiler('c')
-libm = cc.find_library('m', required : false)
-libcblas = cc.find_library('blas')
-liblapacke = cc.find_library('lapacke')
-libndarray = cc.find_library('ndarray')
-
-dep_tp = declare_dependency(link_args : '-lthreadpool')
-
-dep_mpi = dependency('mpi', language: 'c')
-
-deps = [dep_tp, libm, libcblas, liblapacke, libndarray, dep_mpi]
-
-cdata = configuration_data()
-cdata.set10('ARCH_X86', false)
-cdata.set10('ARCH_X86_64', false)
-cdata.set10('HAVE_EXTERNAL_ASM', false)
-
-arch = host_machine.cpu_family()
-if arch.startswith('x86')
- cdata.set10('ARCH_X86', true)
-
- if arch == 'x86_64'
- cdata.set10('ARCH_X86_64', true)
- nasm = find_program('nasm', required : get_option('nasm'))
- if nasm.found()
- cdata.set10('HAVE_EXTERNAL_ASM', true)
- else
- warning('nasm not found, no SIMD will be built')
- endif
- endif
-endif
-
-configure_file(output : 'config.h', output_format : 'c', configuration : cdata)
-
-if nasm.found()
- cdata_asm = configuration_data()
- cdata_asm.set10('ARCH_X86', true)
- cdata_asm.set10('ARCH_X86_64', true)
- cdata_asm.set10('ARCH_X86_32', false)
- configure_file(output : 'config.asm', output_format : 'nasm', configuration : cdata_asm)
-
- if host_machine.system() == 'windows'
- nasm_format = 'win'
- elif host_machine.system() == 'darwin'
- nasm_format = 'macho'
- else
- nasm_format = 'elf'
- endif
- nasm_format += '64'
-
- nasm_gen = generator(nasm,
- output: '@BASENAME@.obj',
- depfile: '@BASENAME@.obj.ndep',
- arguments: [
- '-f', nasm_format,
- '-I', '@SOURCE_DIR@/',
- '-I', '@0@/'.format(meson.current_build_dir()),
- '-MQ', '@OUTPUT@', '-MF', '@DEPFILE@',
- '@EXTRA_ARGS@',
- '@INPUT@',
- '-o', '@OUTPUT@'
- ]
- )
-
- nasm_sources = files(
- 'cpuid.asm',
- 'ndarray.asm',
- 'residual_calc.asm',
- 'transfer_interp.asm',
- )
-
- lib_obj += nasm_gen.process(nasm_sources)
-endif
-
-library('mg2d', lib_src, lib_obj, link_args : ver_flag, dependencies : deps, link_depends : verscript)
-
-# test programs
-test_progs = ['relax', 'relax_mpi', 'mg2d', 'mg2d_mpi']
-foreach t : test_progs
- target = t + '_test'
- executable(target, [target + '.c'] + lib_src, lib_obj, dependencies : deps + [libm])
-endforeach
diff --git a/meson_options.txt b/meson_options.txt
deleted file mode 100644
index 2eb67d7..0000000
--- a/meson_options.txt
+++ /dev/null
@@ -1 +0,0 @@
-option('nasm', type : 'feature', value : 'auto')
diff --git a/residual_calc.c b/residual_calc.c
index 6d58c10..a9efebe 100644
--- a/residual_calc.c
+++ b/residual_calc.c
@@ -70,7 +70,7 @@ struct ResidualCalcInternal {
ResidualCalcTask task;
};
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
void mg2di_residual_calc_line_s1_fma3(size_t linesize, double *dst, double *dst_max,
ptrdiff_t stride, const double *u, const double *rhs,
const double * const diff_coeffs[MG2D_DIFF_COEFF_NB],
@@ -340,7 +340,7 @@ int mg2di_residual_calc_init(ResidualCalcContext *ctx)
case 1:
priv->residual_calc_line = residual_calc_line_s1_c;
priv->residual_add_line = residual_add_line_s1_c;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
if (ctx->cpuflags & MG2DI_CPU_FLAG_FMA3) {
priv->residual_calc_line = mg2di_residual_calc_line_s1_fma3;
priv->residual_add_line = mg2di_residual_add_line_s1_fma3;
@@ -351,7 +351,7 @@ int mg2di_residual_calc_init(ResidualCalcContext *ctx)
case 2:
priv->residual_calc_line = residual_calc_line_s2_c;
priv->residual_add_line = residual_add_line_s2_c;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
if (ctx->cpuflags & MG2DI_CPU_FLAG_FMA3) {
priv->residual_calc_line = mg2di_residual_calc_line_s2_fma3;
priv->residual_add_line = mg2di_residual_add_line_s2_fma3;
diff --git a/transfer.c b/transfer.c
index 7fa41ee..945470e 100644
--- a/transfer.c
+++ b/transfer.c
@@ -61,7 +61,7 @@ typedef struct GridTransferLagrange {
double **fact;
} GridTransferLagrange;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
void mg2di_transfer_interp2d_line_cont_4_fma3(double *dst, ptrdiff_t dst_len,
const double *src, ptrdiff_t src_stride,
const ptrdiff_t *idx_x,
@@ -176,7 +176,7 @@ static int transfer_lagrange_init(GridTransferContext *ctx)
priv->transfer2d_generic = interp2d_transfer_line_generic_4;
priv->stencil = 4;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
if (ctx->cpuflags & MG2DI_CPU_FLAG_FMA3) {
priv->transfer2d_cont = mg2di_transfer_interp2d_line_cont_4_fma3;
}
@@ -188,7 +188,7 @@ static int transfer_lagrange_init(GridTransferContext *ctx)
priv->transfer2d_cont = interp2d_transfer_line_cont_6;
priv->transfer2d_generic = interp2d_transfer_line_generic_6;
priv->stencil = 6;
-#if HAVE_EXTERNAL_ASM
+#if HAVE_NASM
if (ctx->cpuflags & MG2DI_CPU_FLAG_FMA3) {
priv->transfer2d_cont = mg2di_transfer_interp2d_line_cont_6_fma3;
}