commit ae39107e71b68f3f701c943580d96ae8ea74357b
parent 6ea8e2b63c505cc0b8afc24970db6d2f5de5b86c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 6 May 2024 15:48:12 +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 script contains commands
that could be found directly in POSIX make, but which are placed here to
simplify writing the Makefile. Finally, a pkg-config file is provided to
link the library as an external dependency.
In addition to the features already provided in its CMake alternative,
this Makefile supports the use of static libraries and provides an
uninstall target. It also enable compiler and linker options that
activate various hardening features aimed at increasing the security and
robustness of generated binaries. In any case, the main motivation
behind its writing is to use a good old well-established standard with
simple features, available on all UNIX systems, thus simplifying its
portability and support while being much lighter.
Note that the path to the Clipper2 header is no longer defined by
-isystem flags, as CMake used to do, so warnings are not silently
ignored. In fact, -isystem is less common than the -I flag now used. So
it's not a bad choice of option, but a compatibility issue. We disable
compiler warnings by encapsulating the clipper header in a new header
file that disables the compiler options that cause the warnings.
Diffstat:
12 files changed, 385 insertions(+), 138 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,10 +1,12 @@
.gitignore
-CMakeCache.txt
-CMakeFiles
-Makefile
-tmp
[Bb]uild*
*.sw[po]
-*.[ao]
+*.[aod]
+*.so
*~
+test*
+!test*.[ch]
+.config
+.test
tags
+*.pc
diff --git a/Makefile b/Makefile
@@ -0,0 +1,169 @@
+# Copyright (C) 2016-2018, 2021 |Meso|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 = libscpr.a
+LIBNAME_SHARED = libscpr.so
+LIBNAME = $(LIBNAME_$(LIB_TYPE))
+
+################################################################################
+# Library building
+################################################################################
+SRC =\
+ src/scpr_device.c\
+ src/scpr_intersector.c\
+ src/scpr_mesh.c\
+ src/scpr_polygon.c
+OBJ = $(SRC:.c=.o)
+DEP = $(SRC:.c=.d)
+
+build_library: .config $(DEP)
+ @$(MAKE) -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
+
+$(LIBNAME_SHARED): $(OBJ)
+ $(CXX) $(CXXFLAGS) $(DPDC_CFLAGS) -o $@ $(OBJ) $(LDFLAGS_SO) $(DPDC_LIBS)
+
+$(LIBNAME_STATIC): libscpr.o
+ $(AR) -rc $@ $?
+ $(RANLIB) $@
+
+libscpr.o: $(OBJ)
+ $(LD) -r $(OBJ) -o $@
+ $(OBJCOPY) $(OCPFLAGS) $@
+
+.config: config.mk
+ @if ! $(PKG_CONFIG) --atleast-version $(CLIPPER2_VERSION) Clipper2; then \
+ echo "Clipper2 $(CLIPPER2_VERSION) not found" >&2; exit 1; fi
+ @if ! $(PKG_CONFIG) --atleast-version $(POLYGON_VERSION) polygon; then \
+ echo "polygon $(POLYGON_VERSION) not found" >&2; exit 1; fi
+ @if ! $(PKG_CONFIG) --atleast-version $(RSYS_VERSION) rsys; then \
+ echo "rsys $(RSYS_VERSION) not found" >&2; exit 1; fi
+ @echo "config done" > $@
+
+.SUFFIXES: .c .d .o
+.c.d:
+ @$(CXX) $(CXXFLAGS) $(DPDC_CFLAGS) -MM -MT "$(@:.d=.o) $@" $< -MF $@
+
+.c.o:
+ $(CXX) $(CXXFLAGS) $(DPDC_CFLAGS) -DSCPR_SHARED_BUILD -c $< -o $@
+
+################################################################################
+# Installation
+################################################################################
+pkg:
+ sed -e 's#@PREFIX@#$(PREFIX)#g'\
+ -e 's#@VERSION@#$(VERSION)#g'\
+ -e 's#@CLIPPER2_VERSION@#$(CLIPPER2_VERSION)#g'\
+ -e 's#@POLYGON_VERSION@#$(POLYGON_VERSION)#g'\
+ -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g'\
+ scpr.pc.in > scpr.pc
+
+scpr-local.pc: scpr.pc.in
+ sed -e '1d'\
+ -e 's#^includedir=.*#includedir=./src/#'\
+ -e 's#^libdir=.*#libdir=./#'\
+ -e 's#@VERSION@#$(VERSION)#g'\
+ -e 's#@CLIPPER2_VERSION@#$(CLIPPER2_VERSION)#g'\
+ -e 's#@POLYGON_VERSION@#$(POLYGON_VERSION)#g'\
+ -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g'\
+ scpr.pc.in > $@
+
+install: build_library pkg
+ @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib" $(LIBNAME)
+ @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib/pkgconfig" scpr.pc
+ @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/include/star" src/scpr.h
+ @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/share/doc/star-cpr" COPYING README.md
+
+uninstall:
+ rm -f "$(DESTDIR)$(PREFIX)/lib/$(LIBNAME)"
+ rm -f "$(DESTDIR)$(PREFIX)/lib/pkgconfig/scpr.pc"
+ rm -f "$(DESTDIR)$(PREFIX)/include/star/scpr.h"
+ rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-cpr/COPYING"
+ rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-cpr/README.md"
+
+################################################################################
+# Miscellaneous targets
+################################################################################
+all: build_library build_tests
+
+clean: clean_test
+ rm -f $(OBJ) $(TEST_OBJ) $(LIBNAME)
+ rm -f .config .test libscpr.o scpr.pc scpr-local.pc
+
+distclean: clean
+ rm -f $(DEP) $(TEST_DEP)
+
+lint:
+ shellcheck -o all make.sh
+
+################################################################################
+# Tests
+################################################################################
+TEST_SRC =\
+ src/test_scpr_clip.c\
+ src/test_scpr_device.c\
+ src/test_scpr_intersector.c\
+ src/test_scpr_is_in.c\
+ src/test_scpr_mesh.c\
+ src/test_scpr_offset.c\
+ src/test_scpr_polygon.c
+TEST_OBJ = $(TEST_SRC:.c=.o)
+TEST_DEP = $(TEST_SRC:.c=.d)
+
+PKG_CONFIG_LOCAL = PKG_CONFIG_PATH="./:$${PKG_CONFIG_PATH}" $(PKG_CONFIG)
+SCPR_CFLAGS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --cflags scpr-local.pc)
+SCPR_LIBS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --libs scpr-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
+ @$(SHELL) make.sh run_test $(TEST_SRC)
+
+.test: Makefile
+ @$(SHELL) make.sh config_test $(TEST_SRC) > $@
+
+clean_test:
+ $(SHELL) make.sh clean_test $(TEST_SRC)
+
+$(TEST_DEP): config.mk scpr-local.pc
+ @$(CC) $(CFLAGS) $(RSYS_CFLAGS) $(SCPR_CFLAGS) \
+ -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@
+
+$(TEST_OBJ): config.mk scpr-local.pc
+ $(CC) $(CFLAGS) $(RSYS_CFLAGS) $(SCPR_CFLAGS) -c $(@:.o=.c) -o $@
+
+test_scpr_clip\
+test_scpr_device\
+test_scpr_intersector\
+test_scpr_is_in\
+test_scpr_mesh\
+test_scpr_offset\
+test_scpr_polygon \
+: config.mk scpr-local.pc $(LIBNAME)
+ $(CC) $(CFLAGS) -o $@ src/$@.o $(LDFLAGS_EXE) $(SCPR_LIBS) $(RSYS_LIBS) -lm
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -1,119 +0,0 @@
-# Copyright (C) 2016-2018, 2021 |Meso|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/>.
-
-cmake_minimum_required(VERSION 3.1)
-project(scpr C CXX)
-enable_testing()
-
-option(NO_TEST "Do not compile the test programs" OFF)
-
-set(SCPR_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
-
-################################################################################
-# Dependencies
-################################################################################
-get_filename_component(_current_source_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
-set(Clipper2_DIR ${_current_source_dir}/)
-
-find_package(RCMake REQUIRED)
-find_package(RSys 0.6 REQUIRED)
-find_package(Clipper2 1.3 REQUIRED)
-find_package(Polygon 0.0.5 REQUIRED)
-
-include_directories(
- ${Clipper2_INCLUDE_DIR}
- ${Polygon_INCLUDE_DIR}
- ${RSys_INCLUDE_DIR})
-
-set(CMAKE_MODULE_PATH ${RCMAKE_SOURCE_DIR})
-include(rcmake)
-include(rcmake_runtime)
-
-rcmake_append_runtime_dirs(_runtime_dirs RSys Polygon Clipper2)
-
-################################################################################
-# Define targets
-################################################################################
-set(VERSION_MAJOR 0)
-set(VERSION_MINOR 4)
-set(VERSION_PATCH 1)
-set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
-
-set(SCPR_FILES_SRC
- scpr_device.c
- scpr_intersector.c
- scpr_mesh.c
- scpr_polygon.c)
-set(SCPR_FILES_INC_API scpr.h)
-set(SCPR_FILES_INC scpr_c.h)
-set(SCPR_FILES_DOC COPYING README.md)
-rcmake_prepend_path(SCPR_FILES_SRC ${SCPR_SOURCE_DIR})
-rcmake_prepend_path(SCPR_FILES_INC ${SCPR_SOURCE_DIR})
-rcmake_prepend_path(SCPR_FILES_INC_API ${SCPR_SOURCE_DIR})
-rcmake_prepend_path(SCPR_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
-set_source_files_properties(${SCPR_FILES_SRC} PROPERTIES LANGUAGE CXX)
-
-add_library(scpr SHARED ${SCPR_FILES_SRC} ${SCPR_FILES_INC} ${SCPR_FILES_INC_API})
-set_target_properties(scpr PROPERTIES
- DEFINE_SYMBOL SCPR_SHARED_BUILD
- VERSION ${VERSION}
- SOVERSION ${VERSION_MAJOR})
-target_link_libraries(scpr RSys Polygon Clipper2)
-
-if(CMAKE_COMPILER_IS_GNUCXX)
- set_target_properties(scpr PROPERTIES COMPILE_FLAGS "-std=c++17")
-endif()
-
-rcmake_setup_devel(scpr StarCPR ${VERSION} star/scpr_version.h)
-
-################################################################################
-# Define tests
-################################################################################
-if(NOT NO_TEST)
-
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- set(MATH_LIB m)
- endif()
-
- function(new_test _name)
- add_executable(${_name} ${SCPR_SOURCE_DIR}/${_name}.c)
- set_source_files_properties(${SCPR_SOURCE_DIR}/${_name}.c PROPERTIES LANGUAGE C)
- if(CMAKE_COMPILER_IS_GNUCXX)
- set_target_properties(${name} PROPERTIES COMPILE_FLAGS "-std=c99")
- endif()
- target_link_libraries(${_name} scpr RSys ${MATH_LIB})
- add_test(${_name} ${_name})
- endfunction()
- new_test(test_scpr_clip)
- new_test(test_scpr_device)
- new_test(test_scpr_intersector)
- new_test(test_scpr_is_in)
- new_test(test_scpr_offset)
- new_test(test_scpr_mesh)
- new_test(test_scpr_polygon)
- rcmake_copy_runtime_libraries(test_scpr_clip)
-
-endif()
-
-################################################################################
-# Install directories
-################################################################################
-install(TARGETS scpr
- ARCHIVE DESTINATION lib
- LIBRARY DESTINATION lib
- RUNTIME DESTINATION bin)
-install(FILES ${SCPR_FILES_INC_API} DESTINATION include/star/)
-install(FILES ${SCPR_FILES_DOC} DESTINATION share/doc/star-cpr/)
-
diff --git a/config.mk b/config.mk
@@ -0,0 +1,93 @@
+VERSION = 0.5.0
+PREFIX = /usr/local
+
+LIB_TYPE = SHARED
+#LIB_TYPE = STATIC
+
+BUILD_TYPE = RELEASE
+#BUILD_TYPE = DEBUG
+
+################################################################################
+# Tools
+################################################################################
+AR = ar
+CC = cc
+CXX = c++
+LD = ld
+OBJCOPY = objcopy
+PKG_CONFIG = pkg-config
+RANLIB = ranlib
+
+################################################################################
+# Dependencies
+################################################################################
+PCFLAGS_STATIC = --static
+PCFLAGS = $(PCFLAGS_$(LIB_TYPE))
+
+CLIPPER2_VERSION = 1.1.1
+CLIPPER2_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags Clipper2)
+CLIPPER2_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs Clipper2)
+
+POLYGON_VERSION = 0.2
+POLYGON_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags polygon)
+POLYGON_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs polygon)
+
+RSYS_VERSION = 0.14
+RSYS_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags rsys)
+RSYS_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs rsys)
+
+DPDC_CFLAGS = $(CLIPPER2_CFLAGS) $(POLYGON_CFLAGS) $(RSYS_CFLAGS)
+DPDC_LIBS = $(CLIPPER2_LIBS) $(POLYGON_LIBS) $(RSYS_LIBS)
+
+################################################################################
+# Compilation options
+################################################################################
+FLAGS =\
+ -fvisibility=hidden\
+ -fstrict-aliasing\
+ -Wall\
+ -Wcast-align\
+ -Wconversion\
+ -Wextra\
+ -Wmissing-declarations\
+ -Wshadow
+
+CFLAGS_HARDENED =\
+ -D_FORTIFY_SOURCES=2\
+ -fcf-protection=full\
+ -fstack-clash-protection\
+ -fstack-protector-strong
+
+CFLAGS_COMMON =\
+ -std=c89\
+ -Wmissing-prototypes\
+ $(CFLAGS_HARDENED)\
+ $(FLAGS)
+
+CXXFLAGS_COMMON =\
+ -std=c++17\
+ $(CFLAGS_HARDENED)\
+ $(FLAGS)
+
+CFLAGS_DEBUG = -g $(CFLAGS_COMMON)
+CFLAGS_RELEASE = -O2 -DNDEBUG $(CFLAGS_COMMON)
+CFLAGS = $(CFLAGS_$(BUILD_TYPE)) -fPIE # C is only used for the tests
+
+CXXFLAGS_DEBUG = -g $(CXXFLAGS_COMMON)
+CXXFLAGS_RELEASE = -O2 -DNDEBUG $(CXXFLAGS_COMMON)
+CXXFLAGS = $(CXXFLAGS_$(BUILD_TYPE)) -fPIC # C++ is only used for the library
+
+################################################################################
+# Linker options
+################################################################################
+LDFLAGS_HARDENED = -Wl,-z,relro,-z,now
+LDFLAGS_DEBUG = $(LDFLAGS_HARDENED)
+LDFLAGS_RELEASE = -s $(LDFLAGS_HARDENED)
+LDFLAGS = $(LDFLAGS_$(BUILD_TYPE))
+
+LDFLAGS_SO = $(LDFLAGS) -shared -Wl,--no-undefined
+LDFLAGS_EXE = $(LDFLAGS) -pie
+
+OCPFLAGS_DEBUG = --localize-hidden
+OCPFLAGS_RELEASE = --localize-hidden --strip-unneeded
+OCPFLAGS = $(OCPFLAGS_$(BUILD_TYPE))
diff --git a/make.sh b/make.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# Copyright (C) 2016-2018, 2021 |Meso|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/>. */
+
+set -e
+
+config_test()
+{
+ for i in "$@"; do
+ test=$(basename "${i}" ".c")
+ test_list="${test_list} ${test}"
+ printf "%s: %s\n" "${test}" "src/${test}.o"
+ done
+ printf "test_bin: %s\n" "${test_list}"
+}
+
+run_test()
+{
+ for i in "$@"; do
+ test=$(basename "${i}" ".c")
+
+ printf "%s " "${test}"
+ if "./${test}" > /dev/null 2>&1; then
+ printf "\033[1;32mOK\033[m\n"
+ else
+ printf "\033[1;31mError\033[m\n"
+ fi
+ done 2> /dev/null
+}
+
+clean_test()
+{
+ for i in "$@"; do
+ rm -f "$(basename "${i}" ".c")"
+ done
+}
+
+install()
+{
+ prefix=$1
+ shift 1
+
+ mkdir -p "${prefix}"
+
+ for i in "$@"; do
+ dst="${prefix}/${i##*/}"
+
+ if cmp -s "${i}" "${dst}"; then
+ printf "Up to date %s\n" "${dst}"
+ else
+ printf "Installing %s\n" "${dst}"
+ cp "${i}" "${prefix}"
+ fi
+ done
+}
+
+"$@"
diff --git a/scpr.pc.in b/scpr.pc.in
@@ -0,0 +1,14 @@
+prefix=@PREFIX@
+includedir=${prefix}/include
+libdir=${prefix}/lib
+
+Requires: rsys >= @RSYS_VERSION@
+Requires.private: \
+ Clipper2 >= @CLIPPER2_VERSION@, \
+ polygon >= @POLYGON_VERSION@
+Name: Star-Clipper
+Description: Cutting a 2D mesh with a 2D polygon
+Version: @VERSION@
+Libs: -L${libdir} -lscpr
+Libs.private: -lstdc++
+CFlags: -I${includedir}
diff --git a/src/scpr_c.h b/src/scpr_c.h
@@ -17,6 +17,7 @@
#define SCPR_C_H__
#include "scpr.h"
+#include "scpr_clipper.h"
#include <stddef.h>
#include <rsys/rsys.h>
@@ -25,9 +26,6 @@
#include <rsys/dynamic_array.h>
#include <rsys/hash_table.h>
-#undef PI
-#include <clipper2/clipper.h>
-
#define DARRAY_NAME uint32
#define DARRAY_DATA uint32_t
#include <rsys/dynamic_array.h>
diff --git a/src/scpr_clipper.h b/src/scpr_clipper.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2016-2018, 2021 |Meso|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/>. */
+
+#ifndef SCPR_CLIPPER_H
+#define SCPR_CLIPPER_H
+
+#ifdef COMPILER_GCC
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wconversion"
+ #pragma GCC diagnostic ignored "-Wshadow"
+#endif
+
+#include <clipper2/clipper.h>
+
+#ifdef COMPILER_GCC
+ #pragma GCC diagnostic pop
+#endif
+
+#endif /* SCPR_CLIPPER_H */
diff --git a/src/scpr_device.c b/src/scpr_device.c
@@ -22,9 +22,6 @@
#include <rsys/rsys.h>
#include <rsys/double2.h>
-#undef PI
-#include <clipper2/clipper.h>
-
#include <math.h>
#ifdef OS_UNIX
diff --git a/src/scpr_intersector.c b/src/scpr_intersector.c
@@ -24,9 +24,6 @@
#include <rsys/double2.h>
#include <rsys/double3.h>
-#undef PI
-#include <clipper2/clipper.h>
-
#include <stdlib.h>
/*******************************************************************************
diff --git a/src/scpr_mesh.c b/src/scpr_mesh.c
@@ -20,8 +20,6 @@
#include <rsys/logger.h>
#include <polygon.h>
-#undef PI
-#include <clipper2/clipper.h>
/*******************************************************************************
* Helper functions
diff --git a/src/scpr_polygon.c b/src/scpr_polygon.c
@@ -23,9 +23,6 @@
#include <rsys/rsys.h>
#include <rsys/float2.h>
-#undef PI
-#include <clipper2/clipper.h>
-
/*******************************************************************************
* Helper functions
******************************************************************************/