From 098523b825c14184592a8717c2c3becbf6bc3f9f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 23 Nov 2022 16:09:08 +0100 Subject: Switch from meson to configure+make. Meson is an extra dependency and generally sucks. --- Makefile | 72 +++++++++++++++++++++++++ README | 9 ++-- configure | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cpu.c | 4 +- ell_grid_solve.c | 4 +- meson.build | 104 ------------------------------------ meson_options.txt | 1 - residual_calc.c | 6 +-- transfer.c | 6 +-- 9 files changed, 241 insertions(+), 119 deletions(-) create mode 100644 Makefile create mode 100755 configure delete mode 100644 meson.build delete mode 100644 meson_options.txt 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 < config.h < 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; } -- cgit v1.2.3