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.3 - A Program for Computing Primitive Polynomials.
32# Copyright (C) 1999-2024 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_POLYNOMIAL \
163 -D DEBUG_PP_PARSER \
164 -D DEBUG_PP_PRIMALITY_TESTING \
165 -D DEBUG_PP_FACTOR \
166 -D DEBUG_PP_ARITH \
167 -D DEBUG_PP_BIGINT \
168 -D DEBUG_PP_FORCE_UNIT_TEST_FAIL
169#-D DEBUG_PP_FORCE_MEMORY_OVERLOAD
170C_DEBUG_FLAGS = -g3 \
171 -D DEBUG_PP_PRIMPOLY
172endif
173
174
175#============================== ALL Compile and Link Flags =======================
176
177# Gather all C++ and C flags together.
178CPP_FLAGS = $(ARCH) $(CPP_DEBUG_FLAGS) $(CPP_INC) $(CPP_OPTIONS)
179C_FLAGS = $(ARCH) $(C_DEBUG_FLAGS) $(C_INC) $) $(C_OPTIONS)
180
181
182
183#============================== Root directories =============================
184
185# Source file root directories.
186CPP_SRC_DIR = ../SourceCode/Primpoly
187C_SRC_DIR = ../SourceCode/PrimpolyC
188
189# Object file root directories.
190CPP_OBJ_DIR = Bin
191C_OBJ_DIR = BinC
192
193# Executable file root directories.
194CPP_BIN_DIR = Bin
195C_BIN_DIR = BinC
196
197
198#============================== Include Files =======================
199
200# Include files.
201ifeq ($(PLATFORM), cygwin)
202CPP_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++"
203C_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include"
204endif
205
206
207#============================== List of Files ================================
208
209# Object files.
210CPP_OBJ = $(CPP_OBJ_DIR)/ppArith.o \
211 $(CPP_OBJ_DIR)/ppBigInt.o \
212 $(CPP_OBJ_DIR)/ppOperationCount.o \
213 $(CPP_OBJ_DIR)/ppFactor.o \
214 $(CPP_OBJ_DIR)/ppParser.o \
215 $(CPP_OBJ_DIR)/ppPolynomial.o \
216 $(CPP_OBJ_DIR)/ppUnitTest.o
217
218C_OBJ = $(C_OBJ_DIR)/ppArith.o \
219 $(C_OBJ_DIR)/ppFactor.o \
220 $(C_OBJ_DIR)/ppHelperFunc.o \
221 $(C_OBJ_DIR)/ppIO.o \
222 $(C_OBJ_DIR)/ppOrder.o \
223 $(C_OBJ_DIR)/ppPolyArith.o
224
225# Main program object files.
226CPP_OBJ_MAIN = $(CPP_OBJ_DIR)/Primpoly.o
227C_OBJ_MAIN = $(C_OBJ_DIR)/Primpoly.o
228
229# Main program executables.
230CPP_BIN_MAIN = $(CPP_BIN_DIR)/Primpoly.exe
231C_BIN_MAIN = $(C_BIN_DIR)/PrimpolyC.exe
232
233# Archive of source code and build scripts.
234CPP_C_ARCHIVE = Primpoly.tar.gz
235
236
237#============================== Implicit Rules ===============================
238
239# Link all object files to executables.
240$(CPP_BIN_MAIN): $(CPP_OBJ_MAIN) $(CPP_OBJ)
241 $(CPPLINK) $(LFLAGS) $(CPP_OBJ_MAIN) $(CPP_OBJ) -o $(CPP_BIN_MAIN) $(CPP_LIBS)
242
243$(C_BIN_MAIN): $(C_OBJ_MAIN) $(C_OBJ)
244 $(CCLINK) $(LFLAGS) $(C_OBJ_MAIN) $(C_OBJ) -o $(C_BIN_MAIN) $(C_LIBS)
245
246# C++ and C source file compilation to object files.
247$(CPP_BIN_DIR)/%.o : $(CPP_SRC_DIR)/%.cpp
248 $(CPP) -c $(CPP_FLAGS) $< -o $@
249
250$(C_BIN_DIR)/%.o : $(C_SRC_DIR)/%.c
251 $(CC) -c $(C_FLAGS) $< -o $@
252
253# List of all file.o : file.hpp dependencies.
254Primpoly.o: Primpoly.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
255ppArith.o: Primpoly.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
256ppBigInt.o: Primpoly.hpp ppOperationCount.hpp ppBigInt.hpp ppArith.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
257ppOperationCount.o: Primpoly.hpp ppOperationCount.hpp ppBigInt.hpp ppArith.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
258ppFactor.o: Primpoly.hpp ppFactor.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppParser.hpp ppPolynomial.hpp ppUnitTest.hpp
259ppParser.o: Primpoly.hpp ppParser.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppPolynomial.hpp ppUnitTest.hpp
260ppUnitTest.o: Primpoly.hpp ppUnitTest.hpp ppArith.hpp ppOperationCount.hpp ppBigInt.hpp ppFactor.hpp ppParser.hpp ppPolynomial.hpp
261
262ppArith.c: Primpoly.h
263ppOrder.c: Primpoly.h
264ppHelperFunc.c: Primpoly.h
265ppFactor.c: Primpoly.h
266ppPolyArith.c: Primpoly.h
267Primpoly.c: Primpoly.h
268ppIO.c: Primpoly.h
269
270#============================== Targets ======================================
271
272# Make the executables.
273# Also copy the factor tables to the location of the executable.
274c: $(C_BIN_MAIN)
275
276cpp: $(CPP_BIN_MAIN)
277 cp ../SourceCode/Primpoly/FactorTables/c02minus.txt $(CPP_BIN_DIR)
278 cp ../SourceCode/Primpoly/FactorTables/c03minus.txt $(CPP_BIN_DIR)
279 cp ../SourceCode/Primpoly/FactorTables/c05minus.txt $(CPP_BIN_DIR)
280 cp ../SourceCode/Primpoly/FactorTables/c07minus.txt $(CPP_BIN_DIR)
281 cp ../SourceCode/Primpoly/FactorTables/c11minus.txt $(CPP_BIN_DIR)
282
283# Make all executables.
284makeAllExes: c cpp
285
286help:
287 @echo Makefile for MAC OS, Ubuntu Linux Unix systems and Windows/Cygwin for compiling and testing Primpoly.
288 @echo "Build the executables by running"
289 @echo " make"
290 @echo "To remove executables, object files and archive file run"
291 @echo " make clean"
292 @echo "To run regression tests do"
293 @echo " make test"
294 @echo "To create an archive bundle of the source code and scripts run"
295 @echo " make archive"
296
297# Run all tests.
298test: testcpp testc
299
300# Test the C++ program against known good results.
301# Change directory to the executable and run it there so it can find the factor table files it needs.
302# @ in front of the shell command line prevents it from being printed to the console as make runs.
303# - in front of the tells make to ignore a non-zero return code from a shell command.
304# Use sed to remove version and copyright lines which would make the comparision fail every time we change versions.
305testcpp:
306 @echo "Running automated tests for Primpoly, C++ version."
307 -@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
308 -@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
309 -@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
310 -@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
311 -@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
312 -@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
313 -@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
314 -@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
315 -@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
316 -@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
317 -@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
318 -@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
319 -@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
320 -@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
321 -@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
322 -@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
323 -@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
324 -@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
325 diff test.txt knownGood.txt
326 -@cd ..
327 -@echo "Done!"
328
329# Test the C program against known good results.
330testc:
331 -@echo "Running automated tests for Primpoly, C version."
332 -@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
333 -@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
334 -@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
335 -@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
336 -@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
337 -@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
338 -@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
339 -@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
340 -@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
341 -@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
342 -@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
343 -@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
344 -@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
345 -@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
346 -@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
347 diff testc.txt knownGoodC.txt
348 -@echo "Done!"
349
350# Remove all C and C++ object files, executables, factor tables and archives.
351# - 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.
352# @ in front of the shell command line prevents it from being printed to the console as make runs.
353clean:
354 -@echo "Cleaning up object files and executables"
355 -@echo "Sorry, you'll have to manually clean the XCode files."
356 -rm $(CPP_OBJ) $(CPP_OBJ_MAIN) $(CPP_BIN_MAIN) $(CPP_BIN_DIR)/c*.txt # Clean C++ version object files and executables.
357 -rm $(C_OBJ) $(C_OBJ_MAIN) $(C_BIN_MAIN) # Clean C version object files and executables.
358 -rm test.txt testc.txt $(CPP_BIN_DIR)/unitTest.log # Clean test files.
359 -rm -rf PrimpolyXCode/PrimpolyXCode/ # Clean up XCode as much as possible.
360 -rm -rf PrimpolyXCode/Build/
361 -rm -rf PrimpolyXCode/Index/
362 -rm $(CPP_C_ARCHIVE)
363
364# Archive the source code and build scripts.
365# -Clean up all object files and executables first.
366# -Create one *.tar.gz bundle for all the source code.
367# -Exclude .git repository files and all the XCode files.
368# -Make executes each command in a separate shell, so pushd and popd wouldn't take effect if they were on separate lines.
369# -Make the single line look prettier by escaping the newlines.
370# -Why pushd? Because tar won't compress correctly if I call tar in the Project/Build directory and tell tar to use
371# the directory ../../Project. So I pushd to the PrimitivePolynomials dir, call tar with Project dir and
372# copy the archive down to Build/Project.
373archive: clean
374 -@echo "Creating an archive of all source code and build scripts in the /Build directory"
375 -pushd ../.. ;\
376 tar --exclude=".git" --exclude="PrimpolyXCode" -czvf $(CPP_C_ARCHIVE) Project ;\
377 mv $(CPP_C_ARCHIVE) Project/Build/$(CPP_C_ARCHIVE) ;\
378 popd