-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
659 lines (586 loc) · 28.8 KB
/
Copy pathMakefile
File metadata and controls
659 lines (586 loc) · 28.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
################################################################################
# LICENSE #
################################################################################
# This file is part of libtmpl. #
# #
# libtmpl 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. #
# #
# libtmpl 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 libtmpl. If not, see <https://www.gnu.org/licenses/>. #
################################################################################
# Author: Ryan Maguire #
# Date: August 31, 2021 #
################################################################################
# This Makefile currently uses GNU Make features. Use gmake on BSD systems and
# make on macOS and GNU/Linux.
# OPTIONS:
# BUILD_SHARED_LIBS:
# Build a shared object (libtmpl.so) instead of a static one
# (libtmpl.a). Enable with:
# make BUILD_SHARED_LIBS=1 [other-options]
# CC:
# C compiler to be used. Tested with:
# gcc: GNU C compiler.
# clang: LLVM's C compiler.
# Note: Apple's version of clang has also been tested.
# tcc: The Tiny C Compiler.
# pcc: The Portable C Compiler.
# aocc: AMD's optimizing C Compiler.
# icx: Intel's C compiler.
# NOTE: icc not tested, but this compiler is deprecated.
# nvc: NVIDIA's C compiler.
# Enable with:
# make CC=c_compiler_name [other-options]
# AR:
# Set the archiver. This is only used if a static
# build is being created. Enable with:
# make AR=archiver_name [other-options]
# ARCH:
# Manually set the output of uname -m. The Makefile uses this to see
# which architecture you are using in order to select the correct
# assembly code. If you are emulating an architecture, this value
# may not be set correctly. For example, emulating i386 on x86_64,
# uname -m still outputs x86_64. Enabling ARCH=i386 will cause the
# Makefile to select the correct assembly code (the code for i386,
# instead of the code for x86_64). Note that if you disable assembly
# code by passing NO_ASM=1 to the Makefile, this keyword has no
# effect. Enable with:
# make ARCH=name_of_architecture [other-options]
# DEBUG_BUILD:
# Compile with debug symbols. Enable with:
# make DEBUG_BUILD=1 [other-options]
# SIMD_FAST_MATH:
# Enable very aggressive optimizations and use OpenMP to create SIMD
# versions of several of libtmpl's functions. This option is only
# supported by a few compilers (GCC 15+, for example). It enables
# the -ffast-math, -march=native, and -fopenmp-simd flags, and
# requires C23 attributes to protect certain functions like 2Sum and
# 2Prod from these aggressive compiler options. With appropriate
# hardware, this option can double the speed of some functions.
# Enable with:
# make SIMD_FAST_MATH=1 [other-options]
# NOTE:
# Library functions usually have 1-2 ULP error.
# The vectorized versions have roughly twice the amount
# of error, about 1-4 ULP.
# OMP:
# Set OpenMP flags. Useful if you want to build libtmpyl, the Python
# wrapper for libtmpl, and use with numpy arrays for parallel
# computing. Enable with:
# make OMP=1 [other-options]
# NO_LTO:
# Disable the -flto flag (link-time optimization). Some compilers
# do not support -flto and hence this needs to be enabled. For
# NVIDIA's C compiler (nvc) this option is automatically set for you.
# Enable with:
# make NO_LTO=1 [other-options]
# NO_MATH:
# Do not use libtmpl's implementation of libm, the C standard
# mathematical library. You must have C99 or higher support if you
# wish to enable this. The original C89 standard does not require
# float and long double versions of various functions, whereas
# libtmpl makes use of these.
# make NO_MATH=1 [other-options]
# NO_LONGLONG:
# libtmpl provides many functions for integer data types. The config.c
# file will examine the __STDC_VERSION__ macro to check if long long
# is available. If you do not wish to build long long functions at
# all, set this option (for example, you're on a GNU/Linux machine
# where the long and long long data types are the same). Enable with:
# make NO_LONGLONG=1 [other-options]
# NO_INLINE:
# libtmpl allows many smaller functions to be inlined, resulting in
# significant speed boosts in several cases (tmpl_Double_Abs is about
# 2x faster when inlined, for example). The config.c file will check
# the __STDC_VERSION__ macro to see if inline support is available.
# If you do not wish to use inlined code, set this option. Enable via:
# make NO_INLINE=1 [other-options]
# ALWAYS_INLINE:
# Enable the C23 attributes [[gnu::always_inline]] or
# [[clang::always_inline]] for inlined functions. Your compiler
# must support C23 attributes if you want to use this.
# Enable with:
# make ALWAYS_INLINE=1 [other-options]
# NO_IEEE:
# Many functions use unions to take advantage of the IEEE-754
# format for floating-point numbers. This behavior is implementation
# defined in C89, but every compiler I know supports it. Indeed, every
# implementation of libm that I am aware of makes use of this trick.
# The config.c file will check if you have IEEE-754 support and can
# access the bits using a union. If you wish to force the portable
# code to be used, set this option. Note, the portable algorithms are
# significantly slower, in some cases about 10x or worse. Note, in
# C11 and C23, type-punning via unions is well-defined behavior.
# make NO_IEEE=1 [other-options]
# NO_INT:
# It is sometimes useful to have fixed-width (8, 16, 32, and 64) bit
# integers. The C standard does not require these widths be available
# but rather specifies the minimum widths allowed by certain data
# types. The config.c file will try to find the widths of various
# integer types. To skip this, set this option. Enable with:
# make NO_INT=1 [other-options]
# NO_ASM:
# Disable all assembly code when building libtmpl. This is not
# recommended. On several architectures, x86_64 / amd64,
# aarch64 / arm64, ppc64le, several built-in functions like square
# root can be used directly via assembly code. This outperforms the
# C code by a considerable amount. If you would like to force libtmpl
# to use only C code, enable this option. Note, if you are on an
# architecture that libtmpl does not have assembly code for
# (mips, for example) enabling this flag does nothing as the C code
# will be selected automatically. Enable with:
# make NO_ASM=1 [other-options]
# FASM:
# For x86_64 / amd64 you can use either GNU Assembly code (GAS) or
# flat assembly code (FASM). GAS is the default. To use FASM, enable
# this option. Enable with:
# make FASM=1 [other-options]
# USE_MEMCPY:
# Some functions copy data by using a simple for-loop.
# Depending on several things (compiler, libc implementation,
# architecture), it may be faster to use a single call to the memcpy
# function, which is found in the C standard library. Modern
# compilers optimize the for-loop very well, and this outperforms the
# memcpy call in many speed tests. If you would to like to force
# use of the memcpy function, enable this option. Enable with:
# make USE_MEMCPY=1 [other-options]
# USE_VOLATILE:
# Set the TMPL_VOLATILE macro to "volatile" instead of being empty.
# This may be necessary for libtmpl's double-double arithmetic
# routines to work properly. If your compiler supports C23 attributes
# and implements the [[gnu::optimize(...)]] attribute, then you do
# not need to enable this option. The necessary functions will set
# the "no-associative-math" and "fp-contract=off" options to prevent
# aggressive optimizations from ruining them. Enable with:
# make USE_VOLATILE=1 [other-options]
# VOLATILE_SPLIT:
# Force the double splitting method to use the volatile keyword.
# Several architectures (aarch64, ppc64) require the volatile keyword
# for the splitting method to work properly. The splitting method
# is needed to preserve accuracy in functions like cos, sin, the
# Fresnel integrals, and more. This Makefile has a list of known
# architectures that require the volatile keyword to make the split
# work. Thus far they are:
# aarch64
# arm64
# armv7l
# ppc
# ppc64
# ppc64le
# riscv64
# If your architecture is on here, no action is needed. If it is not,
# and you are getting inaccurate results, set VOLATILE_SPLIT=1 when
# building libtmpl. Enable with:
# make VOLATILE_SPLIT=1 [other-options]
# CAUTIOUS_SPLIT:
# Force the double splitting method to use several volatile keywords.
# This could also be called the "paranoid" method. Only one
# architecture tested so far needs this, the i386 / x86 arch. Note
# that x86_64 / amd64 does NOT need this. If you are getting
# inaccurate results for cos, sin, the Fresnel integrals, or any
# other function making use of the splitting technique, and if
# VOLATILE_SPLIT isn't doing the trick, enable this option. Each step
# of the split is declared volatile, which should force the compiler
# to cooperate. This results in a slight reduction of performance,
# but produces accurate results. Enable with:
# make CAUTIOUS_SPLIT=1 [other-options]
# NO_VOLATILE_SPLIT:
# Disable the volatile keyword for the splitting technique, even if
# you are on an architecture that requires it. This is for
# experimenting only and should not be used in actual builds.
# Enable with:
# make NO_VOLATILE_SPLIT=1 [other-options]
# EXTRA_FLAGS:
# Any extra flags you wish to pass to the C compiler.
# For example, with clang you can enable -Weverything via:
# make CC=clang \
# EXTRA_FLAGS="-Weverything -Wno-float-equal -Wno-padded"
# In general, enable with:
# make EXTRA_FLAGS="flags" [other-options]
# Name of the library.
TARGET_LIB_SHARED = libtmpl.so
TARGET_LIB_STATIC = libtmpl.a
# Directory all of the .o files will be placed in.
BUILD_DIR = build
# installation prefix
prefix = /usr/local
# Location of all .c and .S files.
SRC_DIR = src
# Compiler to be used. Override this to whatever you choose.
CC = cc
# Archiver to be used. Only needed if a static build is made.
AR = ar
# The user is allowed to specify their own flags.
EXTRA_FLAGS =
# The architecture libtmpl is being built on.
ARCH = $(shell uname -m)
# Default C flags. GCC, Clang, TCC, PCC, and AOCC handle these ones just fine.
ifdef DEBUG_BUILD
CFLAGS = -I../ -g -fPIC -c
LFLAGS = -fPIC -g -shared
else ifdef SUNCC
CFLAGS = -I../ -xO5 -xipo -KPIC -DNDEBUG -c
LFLAGS = -xO5 -xipo -KPIC -G
else
CFLAGS = -I../ -O3 -flto -fPIC -DNDEBUG -c
LFLAGS = -O3 -fPIC -flto -DNDEBUG -shared
endif
# NVIDIA's C compiler (nvc) does not support the -flto flag.
ifeq ($(CC), nvc)
CFLAGS := $(filter-out -flto, $(CFLAGS))
LFLAGS := $(filter-out -flto, $(LFLAGS))
endif
ifdef NO_LTO
CFLAGS := $(filter-out -flto, $(CFLAGS))
LFLAGS := $(filter-out -flto, $(LFLAGS))
endif
ifdef BUILD_SHARED_LIBS
TARGET_LIB = $(TARGET_LIB_SHARED)
else
TARGET_LIB = $(TARGET_LIB_STATIC)
endif
# Some functions use omp with for-loops (void_pointer functions), if available.
ifdef OMP
CFLAGS += -fopenmp
LFLAGS += -fopenmp
endif
# If libtmpl's libm implementation is not being used, we need to link with libm.
ifdef NO_MATH
LFLAGS += -lm
endif
# Warnings for the build. The bash script has nearly every warning for
# GCC enabled, and if clang is being used the -Weverything warning is set,
# which literally enables every warning. This helps check for standards
# compliance. This Makefile has far fewer warnings enabled.
CWARN = -Wall -Wextra -Wpedantic $(EXTRA_FLAGS)
# Config flags and exclude flags depends on the architecture.
# We'll set these later when we examine the ARCH variable.
CONFIG_FLAGS = $(EXTRA_FLAGS)
EXCLUDE =
# A common trick in numerical analysis with floating-point number is to
# "split" a double, or long double, into two parts to preserve accuracy.
# Some architectures need the volatile keyword to prevent optimizing the split
# away, and some architectures (i386) need several volatile keywords used.
# Below is a non-exhaustive list of architectures that require the keyword.
# If you would like to force enabling of volatile, set VOLATILE_SPLIT=1.
# If you would like to force enabling of several volatile keywords, set
# CAUTIOUS_SPLIT=1. If you want to experiment and disable volatile (which is
# not recommended), set NO_VOLATILE_SPLIT=1.
ifndef NO_VOLATILE_SPLIT
# Architectures known to need the volatile keyword for splitting.
VOLATILE_SPLIT_ARCHS = aarch64 arm64 armv7l ppc ppc64 ppc64le riscv64
CAUTIOUS_SPLIT_ARCHS = i386 x86
# The user can force the volatile split flag to be enabled.
ifdef VOLATILE_SPLIT
VOLATILE_SPLIT_ARCHS += $(ARCH)
endif
# The user can also force the cautious splitting flag to be enabled.
ifdef CAUTIOUS_SPLIT
CAUTIOUS_SPLIT_ARCHS += $(ARCH)
endif
else
# Else for ifndef NO_VOLATILE_SPLIT.
# If the user requested no volatile flags at all, even if they are
# recommended, set these variables to be blank. This should be for
# experimenting only and is not recommended for actual use of libtmpl.
VOLATILE_SPLIT_ARCHS =
CAUTIOUS_SPLIT_ARCHS =
endif
# End of ifndef NO_VOLATILE_SPLIT.
# Enable splitting flags if requested, or if required. Cautious split
# gets precedence over volatile split.
ifeq ($(ARCH), $(filter $(ARCH), $(CAUTIOUS_SPLIT_ARCHS)))
CONFIG_FLAGS += -DTMPL_USE_CAUTIOUS_DOUBLE_SPLIT
else ifeq ($(ARCH), $(filter $(ARCH), $(VOLATILE_SPLIT_ARCHS)))
CONFIG_FLAGS += -DTMPL_USE_VOLATILE_DOUBLE_SPLIT
endif
# End of splitting flags.
# libtmpl will check if long long is available in config.c. If you do not want
# long long functions compiled (for example, you're on a GNU/Linux machine where
# long and long long are the same thing), set this option.
ifdef NO_LONGLONG
CONFIG_FLAGS += -DTMPL_SET_LONGLONG_FALSE
EXCLUDE += ! -name "*llong.c"
endif
# libtmpl provides its own implementation of libm. If you wish to use the
# default libm implementation (if it exists) for your system enable this option.
ifdef NO_MATH
EXCLUDE += ! -name "*_math_*.c" ! -name "*_math_*.S"
else
CONFIG_FLAGS += -DTMPL_SET_USE_MATH_TRUE
endif
# libtmpl will check if inline support is available in config.c. If you do not
# want to inline functions, set this option.
ifndef NO_INLINE
CONFIG_FLAGS += -DTMPL_SET_INLINE_TRUE
EXCLUDE += ! -name "*_no_inline_*.c"
endif
# Users may wish to force inlining functions. The config.c file will only do
# this if the appropriate macro is set.
ifdef ALWAYS_INLINE
CONFIG_FLAGS += -DTMPL_SET_ALWAYS_INLINE_TRUE
endif
# Whether or not to use the strictly portable code, or IEEE-754 compliant code.
ifdef NO_IEEE
CONFIG_FLAGS += -DTMPL_SET_TMPL_USE_IEEE_FALSE
endif
# Whether to use memcpy or for-loops for copying data.
ifdef USE_MEMCPY
CONFIG_FLAGS += -DTMPL_SET_USE_MEMCPY_TRUE
endif
# Whether or not to try and find fixed-width integer data types.
ifdef NO_INT
CONFIG_FLAGS += -DTMPL_SET_NO_INT
endif
# Whether or not to force some computations to use the volatile keyword.
ifdef USE_VOLATILE
CONFIG_FLAGS += -DTMPL_USE_VOLATILE
endif
# Some math routines can be vectorized. Required SIMD instructions and OpenMP.
ifdef SIMD_FAST_MATH
CFLAGS += -ffast-math -march=native -fopenmp-simd -std=c23
LFLAGS += -ffast-math -march=native -fopenmp-simd -std=c23
CONFIG_FLAGS += -DTMPL_SET_USE_SIMD_FAST_MATH_TRUE -std=c23
endif
FASM_SRCS =
ASM_SRCS =
# If the user does not want to use any assembly code (that is, C only) only
# include .c files. Ignore all .S or .fasm files. For x86_64/amd64, aarch64,
# and armv7l (armhf) this is only advised if your C compiler cannot handle
# assembly code. GCC, Clang, and PCC can. TCC cannot.
ifndef NO_ASM
# amd64/x86_64 have various functions built-in, such as sqrt. Use assembly code
# if possible for performance boosts.
ifeq ($(ARCH), $(filter $(ARCH), x86_64 amd64))
# Some function for x86_64 are written in FASM, the Flat Assembler, and have
# much better times than the default C code.
ifdef FASM
FASM_SRCS = $(wildcard $(SRC_DIR)/assembly/fasm/*.fasm)
EXCLUDE += $(patsubst %_x86_64.fasm, ! -name "*%.c", $(notdir $(FASM_SRCS)))
# The default is to use assembly code that GCC can understand. LLVM's clang and
# the Portable C Compiler (PCC) are also able to use this, tested on
# Debian GNU/Linux 11, 12, and 13.
else
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/x86_64/*.S)
EXCLUDE += $(patsubst %_x86_64.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
endif
# End of ifdef FASM.
# x86 / i386 assembly is also available using GNU assembly (GAS).
else ifeq ($(ARCH), $(filter $(ARCH), i386 x86))
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/i386/*.S)
EXCLUDE += $(patsubst %_i386.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
# Same idea, but for aarch64 (arm64). sqrt is also a built-in function.
else ifeq ($(ARCH), $(filter $(ARCH), aarch64 arm64))
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/aarch64/*.S)
EXCLUDE += $(patsubst %_aarch64.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
# Same idea, but for armv7l (armhf). sqrt is also a built-in function.
else ifeq ($(ARCH), $(filter $(ARCH), armv7l))
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/armv7l/*.S)
EXCLUDE += $(patsubst %_armv7l.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
# PowerPC 64-bit big endian.
else ifeq ($(ARCH), $(filter $(ARCH), ppc64))
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/ppc64/*.S)
EXCLUDE += $(patsubst %_ppc64.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
# Lastly, PowerPC 64-bit little endian. Some assembly functions are provided.
else ifeq ($(ARCH), $(filter $(ARCH), ppc64le))
ASM_SRCS = $(wildcard $(SRC_DIR)/assembly/ppc64le/*.S)
EXCLUDE += $(patsubst %_ppc64le.S, ! -name "*%.c", $(notdir $(ASM_SRCS)))
endif
# End of ifeq ($(ARCH), $(filter $(ARCH), x86_64 amd64))
endif
# End of ifndef NO_ASM.
C_SRCS = $(shell find $(SRC_DIR) $(EXCLUDE) -name "*.c")
C_OBJS = $(C_SRCS:%=$(BUILD_DIR)/%.o)
ASM_OBJS = $(ASM_SRCS:%=$(BUILD_DIR)/%.o)
FASM_OBJS = $(FASM_SRCS:%=$(BUILD_DIR)/%.o)
OBJS = $(C_OBJS) $(ASM_OBJS) $(FASM_OBJS)
.PHONY: clean install uninstall all help
all: $(TARGET_LIB)
include/tmpl_config.h: ./config.c
ifeq ($(CC), emcc)
bash emscripten.sh $(CONFIG_FLAGS)
else
$(CC) $(CONFIG_FLAGS) config.c -o config.out
./config.out
rm -f config.out
endif
$(TARGET_LIB_SHARED): $(OBJS) include/tmpl_config.h
@echo "Building libtmpl.so ..."
@-$(CC) $(OBJS) $(LFLAGS) -o $@
$(TARGET_LIB_STATIC): $(OBJS) include/tmpl_config.h
@echo "Building libtmpl.a ..."
@-$(AR) rcs $@ $(OBJS)
$(BUILD_DIR)/%.c.o: %.c include/tmpl_config.h
@mkdir -p $(@D)
$(CC) $(CWARN) $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.S.o: %.S include/tmpl_config.h
@mkdir -p $(@D)
$(CC) $(CWARN) $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.fasm.o: %.fasm include/tmpl_config.h
@mkdir -p $(@D)
fasm $< $@
clean:
rm -f *.o
rm -rf $(BUILD_DIR)
rm -f include/tmpl_config.h
rm -f include/tmpl_inttype.h
rm -f include/tmpl_limits.h
rm -f include/tmpl_float.h
rm -f $(TARGET_LIB_SHARED)
rm -f $(TARGET_LIB_STATIC)
install:
mkdir -p $(prefix)/lib/
mkdir -p $(prefix)/include/libtmpl/
cp -r ./include $(prefix)/include/libtmpl/
ifneq ("$(wildcard $(TARGET_LIB_SHARED))", "")
cp $(TARGET_LIB_SHARED) $(prefix)/lib/$(TARGET_LIB_SHARED)
else
cp $(TARGET_LIB_STATIC) $(prefix)/lib/$(TARGET_LIB_STATIC)
endif
uninstall: clean
rm -rf $(prefix)/include/libtmpl/
rm -f $(prefix)/lib/$(TARGET_LIB_SHARED)
rm -f $(prefix)/lib/$(TARGET_LIB_STATIC)
help:
@echo "\033[0;96mBuild and install libtmpl.\n\nExecutive summary:"
@echo "\033[0;96m\tTo build and install onto your system:"
@echo "\033[0;96m\t\tmake -j && sudo make install"
@echo "\033[0;96m\tTo build and install locally (current user only):"
@echo "\033[0;96m\t\tmake -j && make install prefix=~/.local\n"
@echo "\033[0;96mRecognized commands:"
@echo "\033[0;96m\tmake:"
@echo "\033[0;96m\t\tCompile the library. Use -j to speed this up."
@echo "\033[0;96m\tmake install:"
@echo "\033[0;96m\t\tInstall library into /usr/local/"
@echo "\033[0;96m\t\t(or into the set prefix)."
@echo "\033[0;96m\tmake clean:"
@echo "\033[0;96m\t\tRemove all compiled files in this directory."
@echo "\033[0;96m\tmake uninstall:"
@echo "\033[0;96m\t\tRemove all compiled files from this directory and"
@echo "\033[0;96m\t\tfrom /usr/local/ (or the set prefix)."
@echo "\033[0;96m\tmake help:"
@echo "\033[0;96m\t\tPrint this message.\n"
@echo "\033[0;96mBuild options (see Makefile for more details):"
@echo "\033[0;96m\tBUILD_SHARED_LIBS:"
@echo "\033[0;96m\t\tCreate a shared object (libtmpl.so) instead of a"
@echo "\033[0;96m\t\tstatic library (libtmpl.a)."
@echo "\033[0;96m\t\tExample: make BUILD_SHARED_LIBS=1"
@echo "\033[0;96m\tCC:"
@echo "\033[0;96m\t\tSet the C compiler."
@echo "\033[0;96m\t\tExample: make CC=gcc"
@echo "\033[0;96m\tAR (static builds only):"
@echo "\033[0;96m\t\tSet the archiver."
@echo "\033[0;96m\t\tExample: make AR=ar"
@echo "\033[0;96m\tARCH:"
@echo "\033[0;96m\t\tChange the output of uname -m."
@echo "\033[0;96m\t\tExample: make ARCH=i386"
@echo "\033[0;96m\tDEBUG_BUILD:"
@echo "\033[0;96m\t\tAdd debug symbols to the build."
@echo "\033[0;96m\t\tExample: make DEBUG_BUILD=1"
@echo "\033[0;96m\tSIMD_FAST_MATH:"
@echo "\033[0;96m\t\tEnable aggressive math optimizations and compile"
@echo "\033[0;96m\t\tthe branchless SIMD versions of functions."
@echo "\033[0;91m\t\tNOTE:"
@echo "\033[0;91m\t\t\tThe SIMD versions of functions have slightly"
@echo "\033[0;91m\t\t\tworse errors than their scalar counterparts,"
@echo "\033[0;91m\t\t\tusually 2-4 ULP instead of 1-2. With appropriate"
@echo "\033[0;91m\t\t\thardware this produces a 2-4x boost in speed."
@echo "\033[0;91m\t\t\tA modern compiler is required for this option"
@echo "\033[0;91m\t\t\tto be useful (GCC 15+, for example), and the"
@echo "\033[0;91m\t\t\tOpenMP pragma declare simd must be supported."
@echo "\033[0;91m\t\tWARNING:"
@echo "\033[0;91m\t\t\tC23 attributes and / or compiler pragmas are"
@echo "\033[0;91m\t\t\tused to guard certain functions (like 2Sum)"
@echo "\033[0;91m\t\t\tfrom the -ffast-math (or equivalent)"
@echo "\033[0;91m\t\t\toptimization. Such aggressive optimizations are"
@echo "\033[0;91m\t\t\tneeded to convince GCC to use the SIMD version"
@echo "\033[0;91m\t\t\tbut may break other functions. Unit tests show"
@echo "\033[0;91m\t\t\tthat these attribute / pragma guards work as"
@echo "\033[0;91m\t\t\tintended, but their support is not required by"
@echo "\033[0;91m\t\t\tthe C standard. If your compiler does not"
@echo "\033[0;91m\t\t\tsupport the C23 standard, and if it does not"
@echo "\033[0;91m\t\t\tsupport attributes / pragmas that disable"
@echo "\033[0;91m\t\t\toptimizations, do not enable SIMD_FAST_MATH."
@echo "\033[0;96m\t\tExample: make SIMD_FAST_MATH=1"
@echo "\033[0;96m\tOMP:"
@echo "\033[0;96m\t\tCompile with OpenMP support."
@echo "\033[0;96m\t\tExample: make OMP=1"
@echo "\033[0;96m\tNO_LTO:"
@echo "\033[0;96m\t\tDisable the -flto flag (link-time optimization)."
@echo "\033[0;96m\t\tExample: make NO_LTO=1"
@echo "\033[0;96m\tNO_MATH:"
@echo "\033[0;96m\t\tUse the system libm instead of libtmpl's."
@echo "\033[0;96m\t\tExample: make NO_MATH=1"
@echo "\033[0;96m\tNO_LONGLONG:"
@echo "\033[0;96m\t\tDo not compile any code for long long or"
@echo "\033[0;96m\t\tunsigned long long."
@echo "\033[0;96m\t\tExample: make NO_LONGLONG=1"
@echo "\033[0;96m\tNO_INLINE:"
@echo "\033[0;96m\t\tDo not inline any code."
@echo "\033[0;96m\t\tExample: make NO_INLINE=1"
@echo "\033[0;96m\tALWAYS_INLINE:"
@echo "\033[0;96m\t\tSet the C23 vendor-specific attributes"
@echo "\033[0;96m\t\t[[gnu::always_inline]] or [[llvm::always_inline]]"
@echo "\033[0;96m\t\tfor inlined functions. Requires C23 support."
@echo "\033[0;96m\t\tIgnored by compilers that do not support the"
@echo "\033[0;96m\t\talways_inline attribute."
@echo "\033[0;96m\t\tExample: make ALWAYS_INLINE=1"
@echo "\033[0;96m\tNO_IEEE:"
@echo "\033[0;96m\t\tDo not probe for IEEE-754 support and instead only"
@echo "\033[0;96m\t\tonly use portable C code (NOT RECOMMENDED)."
@echo "\033[0;96m\t\tExample: make NO_IEEE=1"
@echo "\033[0;96m\tNO_INT:"
@echo "\033[0;96m\t\tDo not probe for fixed-width integers and do not"
@echo "\033[0;96m\t\tattempt any type punning (NOT RECOMMENDED)."
@echo "\033[0;96m\t\tExample: make NO_INT=1"
@echo "\033[0;96m\tNO_ASM:"
@echo "\033[0;96m\t\tDo not use any assembly code."
@echo "\033[0;96m\t\tExample: make NO_ASM=1"
@echo "\033[0;91m\t\tNOTE:"
@echo "\033[0;91m\t\t\tThis is NOT recommended on most architectures"
@echo "\033[0;91m\t\t\tsince the assembly code outperforms the C code."
@echo "\033[0;91m\t\t\tSome architectures require this to be set."
@echo "\033[0;91m\t\t\tIf you are on armv7l and lack floating point"
@echo "\033[0;91m\t\t\thardware support, you MUST set NO_ASM=1."
@echo "\033[0;91m\t\t\tThis is because the Makefile assumes armv7l"
@echo "\033[0;91m\t\t\tmachines will have hardware floats, even"
@echo "\033[0;91m\t\t\tthough this is not required."
@echo "\033[0;96m\tFASM (x86_64 / amd64 only):"
@echo "\033[0;96m\t\tUse Flat Assembly (FASM) code instead of"
@echo "\033[0;96m\t\tGNU Assembly (GAS). Requires fasm to be installed."
@echo "\033[0;96m\t\tExample: make FASM=1"
@echo "\033[0;96m\tUSE_MEMCPY:"
@echo "\033[0;96m\t\tUse memcpy for copying data instead of for-loops."
@echo "\033[0;96m\t\tExample: make USE_MEMCPY=1"
@echo "\033[0;96m\tUSE_VOLATILE:"
@echo "\033[0;96m\t\tMake the macro TMPL_VOLATILE expand to 'volatile'"
@echo "\033[0;96m\t\tinstead of nothing. Certain functions like 2Sum"
@echo "\033[0;96m\t\tand routines implementing double-double arithmetic"
@echo "\033[0;96m\t\tmay need this to protect against compiler"
@echo "\033[0;96m\t\toptimizations. This is not required by compilers"
@echo "\033[0;96m\t\tthat respect the C standards requirements for"
@echo "\033[0;96m\t\tfloating-point arithmetic (GCC, Clang, MSVC), but"
@echo "\033[0;96m\t\tit is necessary on other compilers (ICC)."
@echo "\033[0;96m\t\tExample: make USE_VOLATILE=1"
@echo "\033[0;96m\tVOLATILE_SPLIT:"
@echo "\033[0;96m\t\tForce double splits to use the volatile keyword."
@echo "\033[0;96m\t\tExample: make VOLATILE_SPLIT=1"
@echo "\033[0;96m\tCAUTIOUS_SPLIT:"
@echo "\033[0;96m\t\tForce double splits to use several volatiles,"
@echo "\033[0;96m\t\tbreaking the computation into separate lines."
@echo "\033[0;96m\t\tExample: make CAUTIOUS_SPLIT=1"
@echo "\033[0;96m\tNO_VOLATILE_SPLIT:"
@echo "\033[0;96m\t\tForce double splits to never use volatile"
@echo "\033[0;96m\t\t(NOT RECOMMENDED)."
@echo "\033[0;96m\t\tExample: make NO_VOLATILE_SPLIT=1"
@echo "\033[0;96m\tEXTRA_FLAGS:"
@echo "\033[0;96m\t\tAdd extra flags for the C compiler."
@echo "\033[0;96m\t\tExample: make EXTRA_FLAGS=\"-Wno-float-equal\""