1SHELL := /bin/bash # Call shell from /usr/bin/sh instead of /bin/sh. Need this so that commands pushd and popd will be found.
2#========================================================================
3#
4# NAME
5#
6# makefile
7#
8# DESCRIPTION
9#
10# Makefile for MAC OS, Ubuntu Linux Unix systems and
11# Windows/Cygwin for compiling and testing Primpoly.
12#
13# Build the executables by running
14#
15# make
16#
17# To clean up executables, object files, and archives run
18#
19# make clean
20#
21# To run regression tests do
22#
23# make test
24#
25# To create an archive bundle of source code
26#
27# make archive
28#
29# LEGAL
30#
31# Primpoly Version 16.4 - A Program for Computing Primitive Polynomials.
32# Copyright (C) 1999-2025 by Sean Erik O'Connor. All Rights Reserved.
33#
34# This program is free software: you can redistribute it and/or modify
35# it under the terms of the GNU General Public License as published by
36# the Free Software Foundation, either version 3 of the License, or
37# (at your option) any later version.
38#
39# This program is distributed in the hope that it will be useful,
40# but WITHOUT ANY WARRANTY; without even the implied warranty of
41# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42# GNU General Public License for more details.
43#
44# You should have received a copy of the GNU General Public License
45# along with this program. If not, see <http://www.gnu.org/licenses/>.
46#
47# The author's address is seanerikoconnor!AT!gmail!DOT!com
48# with the !DOT! replaced by . and the !AT! replaced by @
49#
50#=============================================================================
51
52# Put this pseudo-target first so make without command line options executes it.
53all: makeAllExes
54
55
56#============================== Configuration ================================
57
58# Find out which operating system we are running on: macOS, Linux, etc.
59UNAME := $(shell uname -s)
60
61# macOS. Tested on my MacBook Pro laptop mid-2015 model with Intel x86_64 architecture, also my MacBook Pro 2021 M1 Max ARM CPU.
62ifeq ($(UNAME), Darwin)
63PLATFORM = mac
64endif
65
66# Linux. Tested on my Ubuntu Linux system running on my Cyperpower PC with a 64-bit AMD CPU.
67ifeq ($(UNAME), Linux)
68PLATFORM = linux
69endif
70
71# Cygwin. For cygwin 2.2 64-bit on Windows 10 64-bit. Not tested. From https://en.wikipedia.org/wiki/Uname
72ifeq ($(UNAME), CYGWIN_NT-10.0)
73PLATFORM = cygwin
74endif
75
76# Default platform is macOS
77ifndef PLATFORM
78PLATFORM = mac
79endif
80
81
82#============================== Compiler, Linker, and CPU architecture =======================
83
84# Type of compiler to use.
85# Mac uses the clang C++/C compiler, same as XCode.
86ifeq ($(PLATFORM), mac)
87CPP = clang++
88CPPLINK = clang++
89CC = clang++ -x c
90CCLINK = clang
91# Ubuntu Linux uses the gcc C++/C compiler.
92else ifeq ($(PLATFORM), linux)
93CPP = g++
94CPPLINK = g++
95CC = gcc -x c
96CCLINK = gcc
97# Windows uses the GNU C++/C compiler.
98else ifeq ($(PLATFORM), cygwin)
99CPP = g++
100CPPLINK = g++
101CC = gcc
102CCLINK = gcc
103endif
104
105# Architecture (CPU type).
106ifeq ($(PLATFORM), mac)
107# The new MacBook Pro uses Apple Silicon CPU based on ARM.
108ARCH = -arch arm64
109# If you specify x86 architecture, the executable will still run due to Apple's Rosetta 2 Intel to ARM code translation,
110# but much more slowly than if you use the native CPU architecture.
111#ARCH = -arch x86_64
112else ifeq ($(PLATFORM), linux)
113ARCH =
114else ifeq ($(PLATFORM), cygwin)
115ARCH =
116endif
117
118
119#============================== Compiler and Linker Settings, Libraries =======================
120
121# Compile the C++20 standard and its libraries.
122ifeq ($(PLATFORM), cygwin)
123CPP_OPTIONS = -std=c++20
124CPP_LIBS = -L"/usr/lib"
125C_OPTIONS =
126C_LIBS = -L"/usr/lib"
127else ifeq ($(PLATFORM), mac)
128CPP_OPTIONS = -std=c++20 -stdlib=libc++
129C_OPTIONS =
130CPP_LIBS =
131C_LIBS =
132else ifeq ($(PLATFORM), linux)
133CPP_OPTIONS = -std=c++20 -D USE_EXPERIMENTAL_FILESYSTEM_GNU_CPP
134C_OPTIONS =
135CPP_LIBS = -lm -lstdc++fs
136C_LIBS = -lm -lstdc++fs
137endif
138
139# Link flags.
140ifeq ($(PLATFORM), mac)
141LFLAGS = $(ARCH)
142else ifeq ($(PLATFORM), linux)
143LFLAGS =
144endif
145
146
147#============================== Optimization =======================
148
149# Select on = optimized code for speed. off = compile for debugging
150OPTIMIZATION = on
151
152# Use the highest optimization level unless weird stuff happens.
153# You can put debug print code here if you wish.
154ifeq ($(OPTIMIZATION), on)
155CPP_DEBUG_FLAGS = -O3
156C_DEBUG_FLAGS = -O3
157# Turn off optimization. Turn on ALL debug print code.
158# You can do this also from source in Primpoly.hpp
159else
160CPP_DEBUG_FLAGS = -g3 \
161 -D DEBUG_PP_PRIMITIVITY \
162 -D DEBUG_PP_SLOW_PRIMITIVITY_CHECK \
163 -D DEBUG_PP_POLYNOMIAL \
164 -D DEBUG_PP_PARSER \
165 -D DEBUG_PP_PRIMALITY_TESTING \
166 -D DEBUG_PP_FACTOR \
167 -D DEBUG_PP_ARITH \
168 -D DEBUG_PP_BIGINT \
169 -D DEBUG_PP_FORCE_UNIT_TEST_FAIL
170#-D DEBUG_PP_FORCE_MEMORY_OVERLOAD
171C_DEBUG_FLAGS = -g3 \
172 -D DEBUG_PP_PRIMPOLY
173endif
174
175
176#============================== ALL Compile and Link Flags =======================
177
178# Gather all C++ and C flags together.
179CPP_FLAGS = $(ARCH) $(CPP_DEBUG_FLAGS) $(CPP_INC) $(CPP_OPTIONS)
180C_FLAGS = $(ARCH) $(C_DEBUG_FLAGS) $(C_INC) $) $(C_OPTIONS)
181
182
183
184#============================== Root directories =============================
185
186# Source file root directories.
187CPP_SRC_DIR = ../SourceCode/Primpoly
188C_SRC_DIR = ../SourceCode/PrimpolyC
189
190# Object file root directories.
191CPP_OBJ_DIR = Bin
192C_OBJ_DIR = BinC
193
194# Executable file root directories.
195CPP_BIN_DIR = Bin
196C_BIN_DIR = BinC
197
198
199#============================== Include Files =======================
200
201# Include files.
202ifeq ($(PLATFORM), cygwin)
203CPP_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++"
204C_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include"
205endif
206
207
208#============================== List of Files ================================
209
210# Object files.
211CPP_OBJ = $(CPP_OBJ_DIR)/ppArith.o \
212 $(CPP_OBJ_DIR)/ppBigInt.o \
213 $(CPP_OBJ_DIR)/ppOperationCount.o \
214 $(CPP_OBJ_DIR)/ppFactor.o \
215 $(CPP_OBJ_DIR)/ppParser.o \
216 $(CPP_OBJ_DIR)/ppPolynomial.o \
217 $(CPP_OBJ_DIR)/ppUnitTest.o
218
219C_OBJ = $(C_OBJ_DIR)/ppArith.o \
220 $(C_OBJ_DIR)/ppFactor.o \
221 $(C_OBJ_DIR)/ppHelperFunc.o \
222 $(C_OBJ_DIR)/ppIO.o \
223 $(C_OBJ_DIR)/ppOrder.o \
224 $(C_OBJ_DIR)/ppPolyArith.o
225
226# Main program object files.
227CPP_OBJ_MAIN = $(CPP_OBJ_DIR)/Primpoly.o
228C_OBJ_MAIN = $(C_OBJ_DIR)/Primpoly.o
229
230# Main program executables.
231CPP_BIN_MAIN = $(CPP_BIN_DIR)/Primpoly.exe
232C_BIN_MAIN = $(C_BIN_DIR)/PrimpolyC.exe
233
234# Archive of source code and build scripts.
235CPP_C_ARCHIVE = Primpoly.tar.gz
236
237
238#============================== Implicit Rules ===============================
239
240# Link all object files to executables.
241$(CPP_BIN_MAIN): $(CPP_OBJ_MAIN) $(CPP_OBJ)
242 $(CPPLINK) $(LFLAGS) $(CPP_OBJ_MAIN) $(CPP_OBJ) -o $(CPP_BIN_MAIN) $(CPP_LIBS)
243
244$(C_BIN_MAIN): $(C_OBJ_MAIN) $(C_OBJ)
245 $(CCLINK) $(LFLAGS) $(C_OBJ_MAIN) $(C_OBJ) -o $(C_BIN_MAIN) $(C_LIBS)
246
247# C++ and C source file compilation to object files.
248$(CPP_BIN_DIR)/%.o : $(CPP_SRC_DIR)/%.cpp
249 $(CPP) -c $(CPP_FLAGS) $< -o $@
250
251$(C_BIN_DIR)/%.o : $(C_SRC_DIR)/%.c
252 $(CC) -c $(C_FLAGS) $< -o $@
253
254# List of all file.o : file.hpp dependencies.
255Primpoly.o: Primpoly.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
256ppArith.o: Primpoly.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
257ppBigInt.o: Primpoly.hpp ppOperationCount.hpp ppBigInt.hpp ppArith.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
258ppOperationCount.o: Primpoly.hpp ppOperationCount.hpp ppBigInt.hpp ppArith.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
259ppFactor.o: Primpoly.hpp ppFactor.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
260ppParser.o: Primpoly.hpp ppParser.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppPolynomial.hpp ppUnitTest.hpp
261ppUnitTest.o: Primpoly.hpp ppUnitTest.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp
262
263ppArith.c: Primpoly.h
264ppOrder.c: Primpoly.h
265ppHelperFunc.c: Primpoly.h
266ppFactor.c: Primpoly.h
267ppPolyArith.c: Primpoly.h
268Primpoly.c: Primpoly.h
269ppIO.c: Primpoly.h
270
271#============================== Targets ======================================
272
273# Make the executables.
274# Also copy the factor tables to the location of the executable.
275c: $(C_BIN_MAIN)
276
277cpp: $(CPP_BIN_MAIN)
278 cp ../SourceCode/Primpoly/FactorTables/c02minus.txt $(CPP_BIN_DIR)
279 cp ../SourceCode/Primpoly/FactorTables/c03minus.txt $(CPP_BIN_DIR)
280 cp ../SourceCode/Primpoly/FactorTables/c05minus.txt $(CPP_BIN_DIR)
281 cp ../SourceCode/Primpoly/FactorTables/c07minus.txt $(CPP_BIN_DIR)
282 cp ../SourceCode/Primpoly/FactorTables/c11minus.txt $(CPP_BIN_DIR)
283
284# Make all executables.
285makeAllExes: c cpp
286
287help:
288 @echo Makefile for MAC OS, Ubuntu Linux Unix systems and Windows/Cygwin for compiling and testing Primpoly.
289 @echo "Build the executables by running"
290 @echo " make"
291 @echo "To remove executables, object files and archive file run"
292 @echo " make clean"
293 @echo "To run regression tests do"
294 @echo " make test"
295 @echo "To create an archive bundle of the source code and scripts run"
296 @echo " make archive"
297
298# Run all tests.
299test: testcpp testc
300
301# Test the C++ program against known good results.
302# Change directory to the executable and run it there so it can find the factor table files it needs.
303# @ in front of the shell command line prevents it from being printed to the console as make runs.
304# - in front of the tells make to ignore a non-zero return code from a shell command.
305# Use sed to remove version and copyright lines which would make the comparision fail every time we change versions.
306testcpp:
307 @echo "Running automated tests for Primpoly, C++ version."
308 -@echo "2 2" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 2 2 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" > ../test.txt
309 -@echo "2 17" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 2 17 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
310 -@echo "2 43" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 2 43 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
311 -@echo "2 62" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 2 62 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
312 -@echo "3 20" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 3 30 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
313 -@echo "5 22" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 5 22 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
314 -@echo "7 16" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 7 16 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
315 -@echo "17 14" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 17 14 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
316 -@echo "137 7" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 137 7 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
317 -@echo "223 8" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 223 8 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
318 -@echo "557 6" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) 557 6 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
319 -@echo "-sc 2 4" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -sc 2 4 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
320 -@echo "-sc 3 5" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -sc 3 5 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
321 -@echo "-a 2 5" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -a 2 5 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
322 -@echo "-t x 1" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -t "x 1"| sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" | sed -e "s/line[ ]*[0-9][0-9]*//" >> ../test.txt
323 -@echo "-t x^4 + x + 1" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -t "x^4 + x + 1" | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
324 -@echo "-t x^3 + x + 2, 3" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -t "x^3 + x + 2, 3" | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
325 -@echo "x ^ 2 + x + 10, 32749" && cd $(CPP_BIN_DIR) && ../$(CPP_BIN_MAIN) -t "x ^ 2 + x + 10, 32749" | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../test.txt
326 diff test.txt knownGood.txt
327 -@cd ..
328 -@echo "Done!"
329
330# Test the C program against known good results.
331testc:
332 -@echo "Running automated tests for Primpoly, C version."
333 -@echo "2 2" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 2 2 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" > ../testc.txt
334 -@echo "2 17" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 2 17 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
335 -@echo " 2 43" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 2 43 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
336 -@echo "2 62" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 2 62 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
337 -@echo "3 3" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 3 30 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
338 -@echo "5 22" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 5 22 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
339 -@echo "7 16" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 7 16 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
340 -@echo "17 14" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 17 14 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
341 -@echo "137 7" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 137 7 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
342 -@echo "223 8" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 223 8 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
343 -@echo "557 6" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) 557 6 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
344 -@echo "-sc 2 4" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) -sc 2 4 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
345 -@echo "-sc 3 5" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) -sc 3 5 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
346 -@echo "-a 2 5" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) -a 2 5 | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
347 -@echo "-t x 1" && cd $(C_BIN_DIR) && ../$(C_BIN_MAIN) -t "x 1" | sed -e "s/Primpoly Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" >> ../testc.txt
348 diff testc.txt knownGoodC.txt
349 -@echo "Done!"
350
351# Remove all C and C++ object files, executables, factor tables and archives.
352# - in front of the tells make to ignore a non-zero return code from a shell command. So we don't stop if any files are missing.
353# @ in front of the shell command line prevents it from being printed to the console as make runs.
354clean:
355 -@echo "Cleaning up object files and executables"
356 -@echo "Sorry, you'll have to manually clean the XCode files."
357 -rm $(CPP_OBJ) $(CPP_OBJ_MAIN) $(CPP_BIN_MAIN) $(CPP_BIN_DIR)/c*.txt # Clean C++ version object files and executables.
358 -rm $(C_OBJ) $(C_OBJ_MAIN) $(C_BIN_MAIN) # Clean C version object files and executables.
359 -rm test.txt testc.txt $(CPP_BIN_DIR)/unitTest.log # Clean test files.
360 -rm -rf PrimpolyXCode/PrimpolyXCode/ # Clean up XCode as much as possible.
361 -rm -rf PrimpolyXCode/Build/
362 -rm -rf PrimpolyXCode/Index/
363 -rm $(CPP_C_ARCHIVE)
364
365# Archive the source code and build scripts.
366# -Clean up all object files and executables first.
367# -Create one *.tar.gz bundle for all the source code.
368# -Exclude .git repository files and all the XCode files.
369# -Make executes each command in a separate shell, so pushd and popd wouldn't take effect if they were on separate lines.
370# -Make the single line look prettier by escaping the newlines.
371# -Why pushd? Because tar won't compress correctly if I call tar in the Project/Build directory and tell tar to use
372# the directory ../../Project. So I pushd to the PrimitivePolynomials dir, call tar with Project dir and
373# copy the archive down to Build/Project.
374archive: clean
375 -@echo "Creating an archive of all source code and build scripts in the /Build directory"
376 -pushd ../.. ;\
377 tar --exclude=".git" --exclude="PrimpolyXCode" -czvf $(CPP_C_ARCHIVE) Project ;\
378 mv $(CPP_C_ARCHIVE) Project/Build/$(CPP_C_ARCHIVE) ;\
379 popd