Skip to content

Commit c228927

Browse files
committed
Makefile: Add compile-time compiler+host platform feature detection
Fixes #1144 This commit extends the Makefiles used for tests to check host compiler and host CPU capabilities when setting archflags with AUTO=1. This leads to SHA3 being enabled for valgrind CT tests in CI, which breaks the test since valgrind does not support those instructions. This is worked around by allowing the user to force values of the compiler feature detection on the command line. Signed-off-by: Hanno Becker <[email protected]>
1 parent a48d98e commit c228927

File tree

7 files changed

+204
-32
lines changed

7 files changed

+204
-32
lines changed

.github/actions/ct-test/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ runs:
3939
- shell: ${{ env.SHELL }}
4040
run: |
4141
make clean
42-
tests func --exec-wrapper="valgrind --error-exitcode=1 --track-origins=yes ${{ inputs.valgrind_flags }}" --cflags="-DMLK_CONFIG_CT_TESTING_ENABLED -DNTESTS=50 ${{ inputs.cflags }}"
42+
MK_COMPILER_SUPPORTS_SHA3=0 tests func --exec-wrapper="valgrind --error-exitcode=1 --track-origins=yes ${{ inputs.valgrind_flags }}" --cflags="-DMLK_CONFIG_CT_TESTING_ENABLED -DNTESTS=50 ${{ inputs.cflags }}"

Makefile

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
build test all \
1717
clean quickcheck check-defined-CYCLES \
1818
size_512 size_768 size_1024 size \
19-
run_size_512 run_size_768 run_size_1024 run_size
19+
run_size_512 run_size_768 run_size_1024 run_size \
20+
host_info
2021

2122
SHELL := /bin/bash
2223
.DEFAULT_GOAL := build
@@ -26,6 +27,8 @@ all: build
2627
W := $(EXEC_WRAPPER)
2728

2829
include test/mk/config.mk
30+
include test/mk/compiler.mk
31+
include test/mk/auto.mk
2932
include test/mk/components.mk
3033
include test/mk/rules.mk
3134

@@ -176,6 +179,30 @@ run_size: \
176179
run_size_768 \
177180
run_size_1024
178181

182+
# Display host and compiler feature detection information
183+
# Shows which architectural features are supported by both the compiler and host CPU
184+
# Usage: make host_info [AUTO=0|1] [CROSS_PREFIX=...]
185+
host_info:
186+
@echo "=== Host and Compiler Feature Detection ==="
187+
@echo "Host Platform: $(HOST_PLATFORM)"
188+
@echo "Target Architecture: $(ARCH)"
189+
@echo "Compiler: $(CC)"
190+
@echo "Cross Prefix: $(if $(CROSS_PREFIX),$(CROSS_PREFIX),<none>)"
191+
@echo "AUTO: $(AUTO)"
192+
@echo ""
193+
ifeq ($(ARCH),x86_64)
194+
@echo "=== x86_64 Feature Support ==="
195+
@echo "AVX2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_AVX2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_AVX2)),✅,❌)"
196+
@echo "SSE2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_SSE2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_SSE2)),✅,❌)"
197+
@echo "BMI2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_BMI2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_BMI2)),✅,❌)"
198+
else ifeq ($(ARCH),aarch64)
199+
@echo "=== AArch64 Feature Support ==="
200+
@echo "SHA3: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_SHA3)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_SHA3)),✅,❌)"
201+
else
202+
@echo "=== Architecture Not Supported ==="
203+
@echo "No specific feature detection available for $(ARCH)"
204+
endif
205+
179206
clean:
180207
-$(RM) -rf *.gcno *.gcda *.lcov *.o *.so
181208
-$(RM) -rf $(BUILD_DIR)

examples/monolithic_build_multilevel_native/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ endif
6161
# Native compilation
6262
ifeq ($(CROSS_PREFIX),)
6363
ifeq ($(HOST_PLATFORM),Linux-x86_64)
64-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
64+
CFLAGS += -mavx2 -mbmi2
6565
CFLAGS += -DMLK_FORCE_X86_64
6666
else ifeq ($(HOST_PLATFORM),Linux-aarch64)
6767
CFLAGS += -DMLK_FORCE_AARCH64
@@ -70,7 +70,7 @@ else ifeq ($(HOST_PLATFORM),Darwin-arm64)
7070
endif
7171
# Cross compilation
7272
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
73-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
73+
CFLAGS += -mavx2 -mbmi2
7474
CFLAGS += -DMLK_FORCE_X86_64
7575
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
7676
CFLAGS += -DMLK_FORCE_AARCH64_EB

examples/multilevel_build_native/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ endif
2828
# Native compilation
2929
ifeq ($(CROSS_PREFIX),)
3030
ifeq ($(HOST_PLATFORM),Linux-x86_64)
31-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
31+
CFLAGS += -mavx2 -mbmi2
3232
CFLAGS += -DMLK_FORCE_X86_64
3333
else ifeq ($(HOST_PLATFORM),Linux-aarch64)
3434
CFLAGS += -DMLK_FORCE_AARCH64
@@ -37,7 +37,7 @@ else ifeq ($(HOST_PLATFORM),Darwin-arm64)
3737
endif
3838
# Cross compilation
3939
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
40-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
40+
CFLAGS += -mavx2 -mbmi2
4141
CFLAGS += -DMLK_FORCE_X86_64
4242
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
4343
CFLAGS += -DMLK_FORCE_AARCH64_EB

test/mk/auto.mk

Lines changed: 106 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,113 @@
11
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
22
#
3-
# Automatically detect system architecture and set preprocessor etc accordingly
3+
# Automatically detect system architecture and set preprocessor flags accordingly
4+
# This file detects host CPU capabilities and combines them with compiler support
5+
# to enable optimal compilation flags.
46

5-
# Native compilation
6-
ifeq ($(CROSS_PREFIX),)
7+
ifndef _AUTO_MK
8+
_AUTO_MK :=
9+
10+
# Helper function to check if host CPU supports a feature
11+
# Usage: $(call check_host_feature,feature_pattern,source_command)
12+
define check_host_feature
13+
$(shell $(2) 2>/dev/null | grep -q "$(1)" && echo 1 || echo 0)
14+
endef
15+
16+
# x86_64 architecture detection
17+
ifeq ($(ARCH),x86_64)
18+
19+
# Host CPU feature detection for x86_64
720
ifeq ($(HOST_PLATFORM),Linux-x86_64)
8-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
9-
CFLAGS += -DMLK_FORCE_X86_64
10-
else ifeq ($(HOST_PLATFORM),Linux-aarch64)
11-
CFLAGS += -DMLK_FORCE_AARCH64
21+
# Linux: Use /proc/cpuinfo
22+
MK_HOST_SUPPORTS_AVX2 := $(call check_host_feature,avx2,cat /proc/cpuinfo)
23+
MK_HOST_SUPPORTS_SSE2 := $(call check_host_feature,sse2,cat /proc/cpuinfo)
24+
MK_HOST_SUPPORTS_BMI2 := $(call check_host_feature,bmi2,cat /proc/cpuinfo)
25+
else ifeq ($(HOST_PLATFORM),Darwin-x86_64)
26+
# macOS: Use sysctl
27+
MK_HOST_SUPPORTS_AVX2 := $(call check_host_feature,AVX2,sysctl -n machdep.cpu.leaf7_features)
28+
MK_HOST_SUPPORTS_SSE2 := $(call check_host_feature,SSE2,sysctl -n machdep.cpu.features)
29+
MK_HOST_SUPPORTS_BMI2 := $(call check_host_feature,BMI2,sysctl -n machdep.cpu.leaf7_features)
30+
else ifneq ($(CROSS_PREFIX),)
31+
# Cross-compilation: assume all features are supported
32+
MK_HOST_SUPPORTS_AVX2 := 1
33+
MK_HOST_SUPPORTS_SSE2 := 1
34+
MK_HOST_SUPPORTS_BMI2 := 1
35+
else
36+
# Other platforms: assume no support
37+
MK_HOST_SUPPORTS_AVX2 := 0
38+
MK_HOST_SUPPORTS_SSE2 := 0
39+
MK_HOST_SUPPORTS_BMI2 := 0
40+
endif # HOST_PLATFORM x86_64
41+
42+
endif # x86_64
43+
44+
# AArch64 architecture detection
45+
ifeq ($(ARCH),aarch64)
46+
47+
# Host CPU feature detection for AArch64
48+
ifeq ($(HOST_PLATFORM),Linux-aarch64)
49+
# Linux: Use /proc/cpuinfo (look for sha3 in Features line)
50+
MK_HOST_SUPPORTS_SHA3 := $(call check_host_feature,sha3,cat /proc/cpuinfo)
1251
else ifeq ($(HOST_PLATFORM),Darwin-arm64)
13-
CFLAGS += -DMLK_FORCE_AARCH64
52+
# macOS: Use sysctl to check for SHA3 support
53+
MK_HOST_SUPPORTS_SHA3 := $(call check_host_feature,1,sysctl -n hw.optional.armv8_2_sha3)
54+
else ifneq ($(CROSS_PREFIX),)
55+
# Cross-compilation: assume all features are supported
56+
MK_HOST_SUPPORTS_SHA3 := 1
57+
else
58+
# Other platforms: assume no support
59+
MK_HOST_SUPPORTS_SHA3 := 0
60+
endif # HOST_PLATFORM aarch64
61+
62+
endif # aarch64
63+
64+
# Only apply CFLAGS modifications if AUTO=1
65+
ifeq ($(AUTO),1)
66+
67+
# x86_64 CFLAGS configuration
68+
ifeq ($(ARCH),x86_64)
69+
CFLAGS += -DMLK_FORCE_X86_64
70+
71+
# Add flags only if both compiler and host support the feature
72+
ifeq ($(MK_COMPILER_SUPPORTS_AVX2)$(MK_HOST_SUPPORTS_AVX2),11)
73+
CFLAGS += -mavx2
1474
endif
15-
# Cross compilation
16-
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
17-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
18-
CFLAGS += -DMLK_FORCE_X86_64
19-
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
20-
CFLAGS += -DMLK_FORCE_AARCH64_EB
21-
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
22-
CFLAGS += -DMLK_FORCE_AARCH64
23-
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
24-
CFLAGS += -DMLK_FORCE_RISCV64
25-
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
26-
CFLAGS += -DMLK_FORCE_RISCV32
27-
else ifneq ($(findstring powerpc64le, $(CROSS_PREFIX)),)
28-
CFLAGS += -DMLK_FORCE_PPC64LE
75+
76+
ifeq ($(MK_COMPILER_SUPPORTS_BMI2)$(MK_HOST_SUPPORTS_BMI2),11)
77+
CFLAGS += -mbmi2
2978
endif
79+
endif # x86_64
80+
81+
# AArch64 CFLAGS configuration
82+
ifeq ($(ARCH),aarch64)
83+
CFLAGS += -DMLK_FORCE_AARCH64
84+
85+
# Add SHA3 flags only if both compiler and host support it
86+
ifeq ($(MK_COMPILER_SUPPORTS_SHA3)$(MK_HOST_SUPPORTS_SHA3),11)
87+
CFLAGS += -march=armv8.4-a+sha3
88+
endif
89+
endif # aarch64
90+
91+
# AArch64 Big Endian CFLAGS configuration
92+
ifeq ($(ARCH),aarch64_be)
93+
CFLAGS += -DMLK_FORCE_AARCH64_EB
94+
endif # aarch64_be
95+
96+
# RISC-V 64-bit CFLAGS configuration
97+
ifeq ($(ARCH),riscv64)
98+
CFLAGS += -DMLK_FORCE_RISCV64
99+
endif # riscv64
100+
101+
# RISC-V 32-bit CFLAGS configuration
102+
ifeq ($(ARCH),riscv32)
103+
CFLAGS += -DMLK_FORCE_RISCV32
104+
endif # riscv32
105+
106+
# PowerPC 64-bit Little Endian CFLAGS configuration
107+
ifeq ($(ARCH),powerpc64le)
108+
CFLAGS += -DMLK_FORCE_PPC64LE
109+
endif # powerpc64le
110+
111+
endif # AUTO=1
112+
113+
endif # _AUTO_MK

test/mk/compiler.mk

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
2+
#
3+
# Compiler feature detection for mlkem-native
4+
# This file detects whether the compiler supports various architectural features
5+
# used by mlkem-native through compile-time tests with C code containing inline assembly.
6+
#
7+
# Feature detection can be overridden by setting the corresponding variable on the command line:
8+
# make MK_COMPILER_SUPPORTS_SHA3=0 # Disable SHA3 detection
9+
# make MK_COMPILER_SUPPORTS_AVX2=0 # Disable AVX2 detection
10+
# make MK_COMPILER_SUPPORTS_BMI2=0 # Disable BMI2 detection
11+
# make MK_COMPILER_SUPPORTS_SSE2=0 # Disable SSE2 detection
12+
13+
ifndef _COMPILER_MK
14+
_COMPILER_MK :=
15+
16+
# Normalize architecture names
17+
ARCH := $(shell uname -m)
18+
ifeq ($(ARCH),arm64)
19+
ARCH := aarch64
20+
endif
21+
22+
# Override ARCH for cross-compilation based on CROSS_PREFIX
23+
ifneq ($(CROSS_PREFIX),)
24+
ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
25+
ARCH := x86_64
26+
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
27+
ARCH := aarch64_be
28+
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
29+
ARCH := aarch64
30+
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
31+
ARCH := riscv64
32+
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
33+
ARCH := riscv32
34+
else ifneq ($(findstring powerpc64le, $(CROSS_PREFIX)),)
35+
ARCH := powerpc64le
36+
endif
37+
endif # CROSS_PREFIX
38+
39+
# x86_64 feature detection
40+
ifeq ($(ARCH),x86_64)
41+
42+
# Test AVX2 support using C with inline assembly
43+
# Can be overridden by setting MK_COMPILER_SUPPORTS_AVX2=0/1 on command line
44+
MK_COMPILER_SUPPORTS_AVX2 ?= $(shell echo 'int main() { __asm__("vpxor %%ymm0, %%ymm1, %%ymm2" ::: "ymm0", "ymm1", "ymm2"); return 0; }' | $(CC) -mavx2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
45+
46+
# Test SSE2 support using C with inline assembly
47+
# Can be overridden by setting MK_COMPILER_SUPPORTS_SSE2=0/1 on command line
48+
MK_COMPILER_SUPPORTS_SSE2 ?= $(shell echo 'int main() { __asm__("pxor %%xmm0, %%xmm1" ::: "xmm0", "xmm1"); return 0; }' | $(CC) -msse2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
49+
50+
# Test BMI2 support using C with inline assembly
51+
# Can be overridden by setting MK_COMPILER_SUPPORTS_BMI2=0/1 on command line
52+
MK_COMPILER_SUPPORTS_BMI2 ?= $(shell echo 'int main() { __asm__("pdep %%eax, %%ebx, %%ecx" ::: "eax", "ebx", "ecx"); return 0; }' | $(CC) -mbmi2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
53+
54+
endif # x86_64
55+
56+
# AArch64 feature detection
57+
ifeq ($(ARCH),aarch64)
58+
59+
# Test SHA3 support (Armv8.4-a+SHA3) using C with inline assembly
60+
# Can be overridden by setting MK_COMPILER_SUPPORTS_SHA3=0/1 on command line
61+
MK_COMPILER_SUPPORTS_SHA3 ?= $(shell echo 'int main() { __asm__("eor3 v0.16b, v1.16b, v2.16b, v3.16b" ::: "v0", "v1", "v2", "v3"); return 0; }' | $(CC) -march=armv8.4-a+sha3 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
62+
63+
endif # aarch64
64+
65+
endif # _COMPILER_MK

test/mk/config.mk

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ CYCLES ?=
8181
OPT ?= 1
8282
RETAINED_VARS := CROSS_PREFIX CYCLES OPT AUTO
8383

84-
ifeq ($(AUTO),1)
85-
include test/mk/auto.mk
86-
endif
87-
8884
BUILD_DIR ?= test/build
8985

9086
MAKE_OBJS = $(2:%=$(1)/%.o)

0 commit comments

Comments
 (0)