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#
5# NAME
6#
7# makefile
8#
9# DESCRIPTION
10#
11# Makefile for UNIX systems and Windows + Cygwin for compiling
12# and testing CRCDemo.
13#
14# Build the executables by running
15#
16# make
17#
18# To clean up executables, object files, and archives run
19#
20# make clean
21#
22# To run regression tests do
23#
24# make test
25#
26# To create an archive bundle of source code
27#
28# make archive
29#
30# LEGAL
31#
32# CRCDemo Version 2.1 - A Program for generating and checking CRC codes.
33# Copyright (C) 1999-2025 by Sean Erik O'Connor. All Rights Reserved.
34#
35# This program is free software: you can redistribute it and/or modify
36# it under the terms of the GNU General Public License as published by
37# the Free Software Foundation, either version 3 of the License, or
38# (at your option) any later version.
39#
40# This program is distributed in the hope that it will be useful,
41# but WITHOUT ANY WARRANTY; without even the implied warranty of
42# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43# GNU General Public License for more details.
44#
45# You should have received a copy of the GNU General Public License
46# along with this program. If not, see <http://www.gnu.org/licenses/>.
47#
48# The author's address is seanerikoconnor!AT!gmail!DOT!com
49# with the !DOT! replaced by . and the !AT! replaced by @
50#
51#=============================================================================
52
53# Put this pseudo-target first so make without command line options executes it.
54all: makeAllExes
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.
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
83
84#============================== Compile and Link Flags =======================
85
86# Select on = optimized code for speed. off = compile for debugging
87OPTIMIZATION = on
88
89# Type of compiler to use.
90# Mac uses the clang C++/C compiler, same as XCode.
91ifeq ($(PLATFORM), mac)
92CPP = clang++
93CPPLINK = clang++
94CC = clang++ -x c
95CCLINK = clang
96# Ubuntu Linux uses the gcc C++/C compiler.
97else ifeq ($(PLATFORM), linux)
98CPP = g++
99CPPLINK = g++
100CC = gcc -x c
101CCLINK = gcc
102# Windows uses the GNU C++/C compiler.
103else ifeq ($(PLATFORM), cygwin)
104CPP = g++
105CPPLINK = g++
106CC = gcc
107CCLINK = gcc
108endif
109
110# Architecture (CPU type).
111ifeq ($(PLATFORM), mac)
112# The new MacBook Pro uses Apple Silicon CPU based on ARM.
113ARCH = -arch arm64
114# If you specify x86 architecture, the executable will still run due to Apple's Rosetta 2 Intel to ARM code translation,
115# but much more slowly than if you use the native CPU architecture.
116#ARCH = -arch x86_64
117else ifeq ($(PLATFORM), linux)
118ARCH =
119else ifeq ($(PLATFORM), cygwin)
120ARCH =
121endif
122
123# Include files.
124ifeq ($(PLATFORM), cygwin)
125CPP_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++"
126C_INC = -I /usr/include -I "/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include"
127endif
128
129# Compile the C++17 standard and its libraries.
130ifeq ($(PLATFORM), cygwin)
131CPP_OPTIONS = -std=c++17
132CPP_LIBS = -L"/usr/lib"
133C_OPTIONS =
134C_LIBS = -L"/usr/lib"
135else ifeq ($(PLATFORM), mac)
136CPP_OPTIONS = -std=c++17 -stdlib=libc++
137C_OPTIONS =
138CPP_LIBS =
139C_LIBS =
140else ifeq ($(PLATFORM), linux)
141CPP_OPTIONS = -std=c++17 -D USE_EXPERIMENTAL_FILESYSTEM_GNU_CPP
142C_OPTIONS =
143CPP_LIBS = -lm -lstdc++fs
144C_LIBS = -lm -lstdc++fs
145endif
146
147# Use the highest optimization level unless weird stuff happens.
148ifeq ($(OPTIMIZATION), on)
149CPP_DEBUG_FLAGS = -O3
150else
151CPP_DEBUG_FLAGS = -g3 \
152 -D DEBUG_PP_POLYNOMIAL \
153 -D DEBUG_PP_PARSER \
154 -D DEBUG_PP_PRIMALITY_TESTING \
155 -D DEBUG_PP_FACTOR \
156 -D DEBUG_PP_ARITH \
157 -D DEBUG_PP_BIGINT \
158 -D DEBUG_PP_FORCE_UNIT_TEST_FAIL
159#-D DEBUG_PP_FORCE_MEMORY_OVERLOAD
160endif
161
162# Gather all C++ and C flags together.
163CPP_FLAGS = $(ARCH) $(CPP_DEBUG_FLAGS) $(CPP_INC) $(CPP_OPTIONS)
164C_FLAGS = $(ARCH) $(C_DEBUG_FLAGS) $(C_INC) $) $(C_OPTIONS)
165
166# Link flags.
167ifeq ($(PLATFORM), mac)
168LFLAGS = $(ARCH)
169else ifeq ($(PLATFORM), linux)
170LFLAGS =
171endif
172
173
174#============================== Root directories =============================
175
176# Source file root directories.
177CPP_SRC_DIR = ../SourceCode
178
179# Object file root directories.
180CPP_OBJ_DIR = Bin
181
182# Executable file root directories.
183CPP_BIN_DIR = Bin
184
185#============================== List of Files ================================
186
187# Object files.
188CPP_OBJ = $(CPP_OBJ_DIR)/shiftRegister.o \
189 $(CPP_OBJ_DIR)/crcCode.o
190
191# Main program object files.
192CPP_OBJ_MAIN = $(CPP_OBJ_DIR)/testCRC.o
193
194# Main program executables.
195CPP_BIN_MAIN = $(CPP_BIN_DIR)/testCRC.exe
196
197# Archive of source code and build scripts.
198CPP_C_ARCHIVE = CRCDemo.tar.gz
199
200#============================== Implicit Rules ===============================
201
202# Link all object files to executables.
203$(CPP_BIN_MAIN): $(CPP_OBJ_MAIN) $(CPP_OBJ)
204 $(CPP) $(LFLAGS) $(CPP_OBJ_MAIN) $(CPP_OBJ) -o $(CPP_BIN_MAIN) $(CPP_LIBS)
205
206
207# C++ and C source file compilation to object files.
208$(CPP_BIN_DIR)/%.o : $(CPP_SRC_DIR)/%.cpp
209 $(CPP) -c $(CPP_FLAGS) $(CPP_INC) $< -o $@
210
211# List of all file.o : file.h dependencies.
212crcCode.o: crcCode.cpp crcCode.h
213shiftRegister.o: shiftRegister.c crcCode.h
214testCRC.o: testCRC.cpp crcCode.h
215
216#============================== Targets ======================================
217
218# Make all the executables.
219makeAllExes: $(CPP_BIN_MAIN)
220
221help:
222 @echo Makefile for MAC OS, Ubuntu Linux Unix systems and Windows/Cygwin for generating and checking CRC codes.
223 @echo "Build the executables by running"
224 @echo " make"
225 @echo "To remove executables, object files and archive file run"
226 @echo " make clean"
227 @echo "To run regression tests do"
228 @echo " make test"
229 @echo "To create an archive bundle of the source code and scripts run"
230 @echo " make archive"
231
232# Test against known good results.
233# @ in front of the shell command line prevents it from being printed to the console as make runs.
234# - in front of the tells make to ignore a non-zero return code from a shell command.
235# Use sed to remove version and copyright lines which would make the comparision fail every time we change versions.
236test: $(CPP_BIN_MAIN)
237 @echo "Running automated tests for CRCDemo."
238 -@$(CPP_BIN_MAIN) | sed -e "s/CRCDemo Version[ ]*[0-9]*\.[0-9]*//" | sed -e "/Copyright.*/d" > test.txt
239 diff test.txt knownGood.txt
240 -@echo "Done!"
241
242# Remove all C and C++ object files, executables and archive.
243# - 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.
244# @ in front of the shell command line prevents it from being printed to the console as make runs.
245clean:
246 -@echo "Cleaning up object files and executables"
247 -rm $(CPP_OBJ) $(CPP_OBJ_MAIN) $(CPP_BIN_MAIN)
248 -rm $(CPP_C_ARCHIVE)
249 -rm test.txt
250
251# Archive the source code and build scripts.
252# -Clean up all object files and executables first.
253# -Create one *.tar.gz bundle for all the source code.
254# -Exclude .git repository files and all the XCode files.
255# -Make executes each command in a separate shell, so pushd and popd wouldn't take effect if they were on separate lines.
256# -Make the single line look prettier by escaping the newlines.
257# -Why pushd? Because tar won't compress correctly if I call tar in the Project/Build directory and tell tar to use
258# the directory ../../Project. So I pushd to the PrimitivePolynomials dir, call tar with Project dir and
259# copy the archive down to Build/Project.
260archive: clean
261 -@echo "Creating an archive of all source code and build scripts in the /Build directory"
262 -pushd ../.. ;\
263 tar --exclude=".git" -czvf $(CPP_C_ARCHIVE) Project ;\
264 mv $(CPP_C_ARCHIVE) Project/Build/$(CPP_C_ARCHIVE) ;\
265 popd