star-sf

Set of surface and volume scattering functions
git clone git://git.meso-star.fr/star-sf.git
Log | Files | Refs | README | LICENSE

commit 644b1e4743bd80c18526ce71be2a2198a9a30b08
parent d27b1b23f62d312e3db54c832511ae5995ba6469
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 18 Jul 2023 14:49:24 +0200

Write a POSIX Makefile to replace CMake

The build procedure is written in POSIX make which the user can
configure via the config.mk file. The make.sh shell script handles the
dynamic parts of the build like detecting supported SIMD instruction
sets. It also contains shell commands that could be directly in the
POSIX make but are placed here to simplify writing the Makefile. Note
that the make.sh script was not designed as a common "configuration"
step: it is automatically called by the Makefile. The construction
procedure is therefore reduced to the single make command.

In addition to the features already provided in its CMake alternative,
this Makefile supports building static libraries and provides an
uninstall target. Anyway, the main motivation behind its writing is to
use a good old well-established standard with simple functionality,
available on all UNIX systems, thereby simplifying its portability and
support while being much lighter.

Diffstat:
M.gitignore | 13++++++++-----
AMakefile | 224+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.mk | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amake.sh | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Assf.pc.in | 11+++++++++++
5 files changed, 469 insertions(+), 5 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,10 +1,13 @@ .gitignore -CMakeCache.txt -CMakeFiles -Makefile -tmp [Bb]uild* *.sw[po] -*.[ao] +*.[aod] +*.so *~ +test* +!test*.[ch] +.config +.simd +.test tags +*.pc diff --git a/Makefile b/Makefile @@ -0,0 +1,224 @@ +# Copyright (C) 2016-2018, 2021-2023 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +.POSIX: +.SUFFIXES: # Clean up default inference rules + +include config.mk + +LIBNAME_STATIC = libssf.a +LIBNAME_SHARED = libssf.so +LIBNAME = $(LIBNAME_$(LIB_TYPE)) + +################################################################################ +# Star-3D building +################################################################################ +SRC =\ + src/ssf.c\ + src/ssf_beckmann_distribution.c\ + src/ssf_blinn_distribution.c\ + src/ssf_bsdf.c\ + src/ssf_fresnel.c\ + src/ssf_fresnel_constant.c\ + src/ssf_fresnel_dielectric_conductor.c\ + src/ssf_fresnel_dielectric_dielectric.c\ + src/ssf_fresnel_no_op.c\ + src/ssf_lambertian_reflection.c\ + src/ssf_microfacet_distribution.c\ + src/ssf_microfacet_reflection.c\ + src/ssf_phase.c\ + src/ssf_phase_discrete.c\ + src/ssf_phase_hg.c\ + src/ssf_phase_rayleigh.c\ + src/ssf_phase_rdgfa.c\ + src/ssf_pillbox_distribution.c\ + src/ssf_specular_dielectric_dielectric_interface.c\ + src/ssf_specular_reflection.c\ + src/ssf_thin_specular_dielectric.c +OBJ = $(SRC:.c=.o) +DEP = $(SRC:.c=.d) + +build_library: + +build_library__: .config $(DEP) + @$(MAKE) -f.simd -fMakefile $$(for i in $(DEP); do echo -f $${i}; done) \ + $$(if [ -n "$(LIBNAME)" ]; then\ + echo "$(LIBNAME)";\ + else\ + echo "$(LIBNAME_SHARED)";\ + fi) + +$(DEP) $(OBJ): config.mk .simd + +$(LIBNAME_SHARED): $(OBJ) + $(CC) $(CFLAGS) $(CFLAGS_SIMD) $(DPDC_CFLAGS) -o $@ $(OBJ) $(LDFLAGS) $(SOFLAGS) $(DPDC_LIBS) + +$(LIBNAME_STATIC): $(OBJ) + $(AR) -rc $@ $? + $(RANLIB) $@ + +.config__: config.mk make.sh .simd + @if [ "$(SIMD_WIDTH)" = "128" ] || [ "$(SIMD_WIDTH)" = "256" ]; then \ + if ! $(PKG_CONFIG) --atleast-version $(RSIMD_VERSION) rsimd; then \ + echo "rsimd $(RSIMD_VERSION) not found"; exit 1; fi; fi + @if ! $(PKG_CONFIG) --atleast-version $(RSYS_VERSION) rsys; then \ + echo "rsys $(RSYS_VERSION) not found"; exit 1; fi + @if ! $(PKG_CONFIG) --atleast-version $(SSP_VERSION) star-sp; then \ + echo "star-sp $(SSP_VERSION) not found"; exit 1; fi + @echo "config done" > .config + +.simd: make.sh config.mk + @$(SHELL) make.sh config_simd > $@ + +.SUFFIXES: .c .d .o +.c.d: + @$(CC) $(CFLAGS) $(CFLAGS_SIMD) $(DPDC_CFLAGS) -MM -MT "$(@:.d=.o) $@" $< -MF $@ + +.c.o: + $(CC) $(CFLAGS) $(CFLAGS_SIMD) $(DPDC_CFLAGS) -DSSF_SHARED_BUILD -c $< -o $@ + +################################################################################ +# Miscellaneous targets +################################################################################ +all: build_library build_tests + +clean: clean_test + rm -f $(OBJ) $(TEST_OBJ) $(LIBNAME) .config .simd .test .simd ssf.pc ssf-local.pc + +distclean: clean + rm -f $(DEP) $(TEST_DEP) + +lint: + shellcheck -o all make.sh + +.config \ +build_library \ +pkg \ +ssf-local.pc \ +: .simd + @$(MAKE) -f.simd -fMakefile $@__ + +################################################################################ +# Installation +################################################################################ +PKG_RSIMD = rsimd >= $(RSIMD_VERSION), +PKG_SIMD_128 = $(PKG_RSIMD) +PKG_SIMD_256 = $(PKG_RSIMD) +PKG_SIMD = $(PKG_SIMD_$(SIMD_WIDTH)) + +pkg__: + @echo "Setup ssf.pc" + @sed -e 's#@PREFIX@#$(PREFIX)#g'\ + -e 's#@VERSION@#$(VERSION)#g'\ + -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g'\ + -e 's#@SSP_VERSION@#$(SSP_VERSION)#g'\ + -e 's#@SIMD@#$(PKG_SIMD)#g'\ + ssf.pc.in > ssf.pc + +ssf-local.pc: ssf.pc.in +ssf-local.pc__: + @echo "Setup ssf.pc" + @sed -e '1d'\ + -e 's#^includedir=.*#includedir=./src/#'\ + -e 's#^libdir=.*#libdir=./#'\ + -e 's#@VERSION@#$(VERSION)#g'\ + -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g'\ + -e 's#@SSP_VERSION@#$(SSP_VERSION)#g'\ + -e 's#@SIMD@#$(PKG_SIMD)#g'\ + ssf.pc.in > ssf-local.pc + +install: build_library pkg + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib" $(LIBNAME) + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib/pkgconfig" ssf.pc + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/include/star" src/ssf.h + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/shared/doc/star-sf" COPYING README.md + +uninstall: + rm -f "$(DESTDIR)$(PREFIX)/lib/$(LIBNAME)" + rm -f "$(DESTDIR)$(PREFIX)/lib/pkgconfig/ssf.pc" + rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-sf/COPYING" + rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-sf/README.md" + rm -f "$(DESTDIR)$(PREFIX)/include/star/ssf.h" + +################################################################################ +# Tests +################################################################################ +TEST_SRC =\ + src/test_ssf_beckmann_distribution.c\ + src/test_ssf_blinn_distribution.c\ + src/test_ssf_bsdf.c\ + src/test_ssf_fresnel.c\ + src/test_ssf_fresnel_constant.c\ + src/test_ssf_fresnel_dielectric_conductor.c\ + src/test_ssf_fresnel_dielectric_dielectric.c\ + src/test_ssf_fresnel_no_op.c\ + src/test_ssf_lambertian_reflection.c\ + src/test_ssf_microfacet_distribution.c\ + src/test_ssf_microfacet_reflection.c\ + src/test_ssf_phase.c\ + src/test_ssf_phase_discrete.c\ + src/test_ssf_phase_hg.c\ + src/test_ssf_phase_rayleigh.c\ + src/test_ssf_phase_rdgfa.c\ + src/test_ssf_pillbox_distribution.c\ + src/test_ssf_specular_dielectric_dielectric_reflection.c\ + src/test_ssf_specular_reflection.c\ + src/test_ssf_thin_specular_dielectric.c +TEST_OBJ = $(TEST_SRC:.c=.o) +TEST_DEP = $(TEST_SRC:.c=.d) + +PKG_CONFIG_LOCAL = PKG_CONFIG_PATH="./:$${PKG_CONFIG_PATH}" $(PKG_CONFIG) +SSF_CFLAGS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --cflags ssf-local.pc) +SSF_LIBS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --libs ssf-local.pc) + +build_tests: build_library $(TEST_DEP) .test + @$(MAKE) -fMakefile -f.test $$(for i in $(TEST_DEP); do echo -f"$${i}"; done) test_bin + +test: build_tests .simd + @$(SHELL) make.sh run_test $(TEST_SRC) + +.test: Makefile + @$(SHELL) make.sh config_test $(TEST_SRC) > .test + +clean_test: + @$(SHELL) make.sh clean_test $(TEST_SRC) + +$(TEST_DEP) $(TEST_OBJ): config.mk + +test_ssf_beckmann_distribution \ +test_ssf_blinn_distribution \ +test_ssf_bsdf \ +test_ssf_fresnel \ +test_ssf_fresnel_constant \ +test_ssf_fresnel_dielectric_conductor \ +test_ssf_fresnel_dielectric_dielectric \ +test_ssf_fresnel_no_op \ +test_ssf_lambertian_reflection \ +test_ssf_microfacet_distribution \ +test_ssf_microfacet_reflection \ +test_ssf_phase \ +test_ssf_phase_discrete \ +test_ssf_phase_hg \ +test_ssf_phase_rayleigh \ +test_ssf_phase_rdgfa \ +test_ssf_pillbox_distribution \ +test_ssf_specular_dielectric_dielectric_reflection \ +test_ssf_specular_reflection \ +test_ssf_thin_specular_dielectric \ +: config.mk ssf-local.pc + $(CC) -o $@ src/$@.o $(RSYS_LIBS) $(SSF_LIBS) $(SSP_LIBS) -lm + +$(TEST_OBJ): ssf-local.pc + $(CC) $(CFLAGS) $(RSYS_CFLAGS) $(SSF_CFLAGS) $(SSP_CFLAGS)-c $(@:.o=.c) -o $@ diff --git a/config.mk b/config.mk @@ -0,0 +1,86 @@ +VERSION = 0.8.0 +PREFIX = /usr/local + +LIB_TYPE = SHARED +#LIB_TYPE = STATIC + +BUILD_TYPE = RELEASE +#BUILD_TYPE = DEBUG + +# If not set, SIMD WIDTH is retrieved from host CPU +#SIMD_WIDTH = NONE +#SIMD_WIDTH = 128 +#SIMD_WIDTH = 256 + +################################################################################ +# Tools +################################################################################ +AR = ar +CC = cc +PKG_CONFIG = pkg-config +RANLIB = ranlib + +################################################################################ +# Dependencies +################################################################################ +PCFLAGS_STATIC = --static +PCFLAGS = $(PCFLAGS_$(LIB_TYPE)) + +RSIMD_VERSION = 0.3 +RSIMD_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags rsimd) +RSIMD_CFLAGS_128 = $(RSIMD_CFLAGS) +RSIMD_CFLAGS_256 = $(RSIMD_CFLAGS) +RSIMD_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs rsimd) +RSIMD_LIBS_128 = $(RSIMD_LIBS) +RSIMD_LIBS_256 = $(RSIMD_LIBS) + +RSYS_VERSION = 0.6 +RSYS_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags rsys) +RSYS_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs rsys) + +SSP_VERSION=0.12 +SSP_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags star-sp) +SSP_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs star-sp) + +DPDC_CFLAGS_SIMD_128 = $(RSIMD_CFLAGS) +DPDC_CFLAGS_SIMD_256 = $(RSIMD_CFLAGS) +DPDC_LIBS_SIMD_128 = $(RSIMD_LIBS) +DPDC_LIBS_SIMD_256 = $(RSIMD_LIBS) + +DPDC_CFLAGS=$(RSIMD_CFLAGS_$(SIMD_WIDTH)) $(RSYS_CFLAGS) $(SSP_CFLAGS) +DPDC_LIBS=$(RSIMD_LIBS_$(SIMD_WIDTH)) $(RSYS_LIBS) $(SSP_LIBS) -lm + +################################################################################ +# Compilation options +################################################################################ +WFLAGS =\ + -Wall\ + -Wcast-align\ + -Wconversion\ + -Wextra\ + -Wmissing-declarations\ + -Wmissing-prototypes\ + -Wshadow +CFLAGS_SIMD_128 = -DSSF_USE_SIMD_128 +CFLAGS_SIMD_256 = $(CFLAGS_SIMD_128) -DSSF_USE_SIMD_256 +CFLAGS_SIMD = $(CFLAGS_SIMD_$(SIMD_WIDTH)) +CFLAGS_COMMON =\ + -std=c89\ + -pedantic\ + -fPIC\ + -fvisibility=hidden\ + -fstrict-aliasing\ + $(WFLAGS)\ + +CFLAGS_RELEASE = -O2 -DNDEBUG $(CFLAGS_COMMON) +CFLAGS_DEBUG = -g $(CFLAGS_COMMON) +CFLAGS = $(CFLAGS_$(BUILD_TYPE)) + +################################################################################ +# Linker options +################################################################################ +SOFLAGS = -shared -Wl,--no-undefined + +LDFLAGS_DEBUG = +LDFLAGS_RELEASE = -s +LDFLAGS = $(LDFLAGS_$(BUILD_TYPE)) diff --git a/make.sh b/make.sh @@ -0,0 +1,140 @@ +#!/bin/sh -e + +# Copyright (C) 2016-2018, 2021-2023 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +################################################################################ +# Helper functions +################################################################################ +# Print the value of a variable in config.mk +showvar() +{ + # To avoid messages from Make being displayed instead of the value of the + # queried variable, we redirect its output to /dev/null and open a new file + # descriptor to stdout to print the variable +<< EOF make -f 3>&1 1>/dev/null 2>&1 - || kill -HUP $$ +.POSIX: +include config.mk +showvar: + @1>&3 echo \$(${1}) +EOF + exec 3<&- # Close file descriptor 3 +} + +check_cpuflag() +{ + sed -n "/^flags[[:blank:]]\{1,\}:/{p;q}" /proc/cpuinfo \ +| sed "s/.*[[:blank:]]\{1,\}\($1\)[[:blank:]]\{1,\}.*/\1/" +} + +################################################################################ +# Main functions +################################################################################ +config_simd() +{ + simd_width="$(showvar SIMD_WIDTH)" + pkg_config="$(showvar PKG_CONFIG)" + avx="$(check_cpuflag avx)" + if [ -z "${simd_width}" ]; then + if ! ${pkg_config} --exists rsimd; then + simd_width="NONE" + elif [ -n "${avx}" ]; then + simd_width="256" + else + simd_width="128" + fi + fi + printf "SIMD_WIDTH = %s\n" "${simd_width}" +} + +config_test() +{ + for i in "$@"; do + test=$(basename "${i}" ".c") + test_list="${test_list} ${test}" + printf "%s: src/%s.o\n" "${test}" "${test}" + done + printf "test_bin: %s\n" "${test_list}" +} + +check() +{ + name="$1" + prog="$2" + shift 2 + + printf "%s " "${name}" + if ./"${prog}" "$@" > /dev/null 2>&1; then + printf "\e[1;32mOK\e[m\n" + else + printf "\e[1;31mError\e[m\n" + fi +} + + +run_test() +{ + for i in "$@"; do + test=$(basename "${i}" ".c") + if [ "${test}" != "test_ssf_phase_rdgfa" ]; then + check "${test}" "${test}" + else + macro="SIMD_WIDTH" + value="[^[:blank:]]\{0,\}" + spaces="[[:space:]]\{0,\}" + simd_width=$(sed "s/${macro}${spaces}=${spaces}\(${value}\)${spaces}$/\1/" .simd) + if [ "${simd_width}" = "256" ]; then + check "${test}_simd_256" "${test}" simd_256 + fi + if [ "${simd_width}" = "256" ] || [ "${simd_width}" = 128 ]; then + check "${test}_simd_128" "${test}" simd_128 + fi + check "${test}_simd_none" "${test}" simd_none + fi + done 2> /dev/null +} + +clean_test() +{ + for i in "$@"; do + rm -f "$(basename "${i}" ".c")" + done +} + +install() +{ + prefix=$1 + shift 1 + + for i in "$@"; do + # Remove the "src" directory and append the "prefix" + dst="${prefix}/${i#*/}" + + # Create the Install directory if required + dir="${dst%/*}" + if [ ! -d "${dir}" ]; then + mkdir -p "${dir}" + fi + + if cmp -s "${i}" "${dst}"; then + printf "Up to date %s\n" "${dst}" + else + printf "Installing %s\n" "${dst}" + cp "${i}" "${dst}" + fi + done +} + +"$@" diff --git a/ssf.pc.in b/ssf.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +includedir=${prefix}/include +libdir=${prefix}/lib + +Requires: rsys >= @RSYS_VERSION@ +Requires.private: @SIMD@ star-sp >= @SSP_VERSION@ +Name: Star Scattering Functions +Description: Star-SF library +Version: @VERSION@ +Libs: -L${libdir} -lssf +CFlags: -I${includedir}