Skip to content

Commit 54978e6

Browse files
authored
feat: full support for features and profiles (#1181)
2 parents 87583f7 + 7ef6f22 commit 54978e6

39 files changed

+2977
-1182
lines changed

.github/workflows/CI.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ jobs:
2929
- {compiler: gcc, version: 13}
3030
- {compiler: gcc, version: 14}
3131
- {compiler: gcc, version: 15}
32-
- {compiler: intel, version: 2025.1}
32+
- {compiler: intel, version: 2025.2}
3333
exclude:
3434
- os: macos-14 # No Intel on MacOS anymore since 2024
3535
toolchain: {compiler: intel, version: '2025.1'}
36+
- os: macos-14 # Intel compiler does not support ARM (macos-14)
37+
toolchain: {compiler: intel, version: '2025.2'}
3638
- os: macos-14 # gcc@10 not available on macos-14 (ARM64)
3739
toolchain: {compiler: gcc, version: 10}
3840
- os: windows-latest # Doesn't pass build and tests yet
39-
toolchain: {compiler: intel, version: '2025.1'}
41+
toolchain: {compiler: intel, version: '2025.2'}
4042
- os: windows-latest # gcc 14 not available on Windows yet
4143
toolchain: {compiler: gcc, version: 14}
4244
- os: windows-latest # gcc 15 not available on Windows yet

ci/meta_tests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pushd metapackage_stdlib
2828
popd
2929

3030
pushd metapackage_minpack
31-
"$fpm" build --verbose
32-
"$fpm" run --verbose
31+
"$fpm" build --verbose --flag " -Wno-external-argument-mismatch"
32+
"$fpm" run --verbose --flag " -Wno-external-argument-mismatch"
3333
popd
3434

3535
pushd metapackage_mpi

ci/run_tests.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ popd
317317

318318
# Test shared library dependencies
319319
pushd shared_lib
320-
"$fpm" build || EXIT_CODE=$?
320+
"$fpm" build --verbose || EXIT_CODE=$?
321321
test $EXIT_CODE -eq 0
322322
popd
323323

@@ -374,5 +374,9 @@ popd
374374
# Test custom build directory functionality
375375
bash "../ci/test_custom_build_dir.sh" "$fpm" hello_world
376376

377+
# Test FPM features functionality
378+
echo "=== Testing FPM Features Functionality ==="
379+
bash "../ci/test_features.sh" "$fpm"
380+
377381
# Cleanup
378382
rm -rf ./*/build

ci/test_features.sh

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
#!/usr/bin/env bash
2+
set -exo pipefail
3+
4+
# Test script for FPM features functionality
5+
# Usage: ./test_features.sh [fpm_executable]
6+
# Note: This script should be run from the repo root or integrated into run_tests.sh
7+
8+
if [ "$1" ]; then
9+
fpm="$1"
10+
else
11+
# Default to the fpm passed from run_tests.sh or system fpm
12+
fpm="${fpm:-fpm}"
13+
fi
14+
15+
echo "Testing FPM features functionality"
16+
17+
echo "=== Testing features_demo package ==="
18+
19+
# Test 1: Basic features - debug feature
20+
pushd "features_demo"
21+
echo "Test 1: Basic debug feature"
22+
rm -rf build
23+
"$fpm" run --features debug > output.txt
24+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled"; exit 1; }
25+
echo "✓ Debug feature works"
26+
27+
# Test 2: Profile usage - development profile (includes debug)
28+
echo "Test 2: Development profile (debug feature)"
29+
rm -rf build
30+
"$fpm" run --profile development --target features_demo > output.txt
31+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled in development profile"; exit 1; }
32+
echo "✓ Development profile works"
33+
34+
# Test 3: Multiple features
35+
echo "Test 3: Multiple features (debug + openmp)"
36+
rm -rf build
37+
"$fpm" run --features debug,openmp --target features_demo > output.txt
38+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled with multiple features"; exit 1; }
39+
grep -q "OpenMP support enabled" output.txt || { echo "ERROR: OpenMP not enabled with multiple features"; exit 1; }
40+
echo "✓ Multiple features work"
41+
42+
# Test 4: Feature-specific executable (debug_demo only available with debug feature)
43+
echo "Test 4: Feature-specific executable"
44+
rm -rf build
45+
"$fpm" run --features debug --target debug_demo > output.txt
46+
grep -q "Debug Demo Program" output.txt || { echo "ERROR: Debug Demo Program not found"; exit 1; }
47+
grep -q "Debug mode: ON" output.txt || { echo "ERROR: Debug mode not ON in debug_demo"; exit 1; }
48+
echo "✓ Feature-specific executable works"
49+
50+
# Test 5: Profile with multiple features - production profile (release + openmp)
51+
echo "Test 5: Production profile (release + openmp)"
52+
rm -rf build
53+
"$fpm" run --profile production --target features_demo > output.txt
54+
grep -q "RELEASE mode enabled" output.txt || { echo "ERROR: RELEASE mode not enabled in production profile"; exit 1; }
55+
grep -q "OpenMP support enabled" output.txt || { echo "ERROR: OpenMP not enabled in production profile"; exit 1; }
56+
# Should NOT have debug
57+
if grep -q "DEBUG mode enabled" output.txt; then
58+
echo "ERROR: DEBUG mode should not be enabled in production profile"
59+
exit 1
60+
fi
61+
echo "✓ Production profile works"
62+
63+
# Test 6: No features - baseline behavior
64+
echo "Test 6: No features (baseline)"
65+
rm -rf build
66+
"$fpm" run --target features_demo > output.txt
67+
# Should have neither DEBUG nor RELEASE without explicit features
68+
if grep -q "DEBUG mode enabled" output.txt; then
69+
echo "ERROR: DEBUG mode should not be enabled in baseline"
70+
exit 1
71+
fi
72+
if grep -q "RELEASE mode enabled" output.txt; then
73+
echo "ERROR: RELEASE mode should not be enabled in baseline"
74+
exit 1
75+
fi
76+
if ! grep -q "Features: NONE" output.txt && ! grep -q "Demo completed successfully" output.txt; then
77+
echo "ERROR: Expected baseline features output not found"
78+
exit 1
79+
fi
80+
echo "✓ Baseline (no features) works"
81+
82+
# Test 7: Error handling - invalid feature
83+
echo "Test 7: Error handling for invalid feature"
84+
rm -rf build
85+
if ! "$fpm" run --features nonexistent --target features_demo > /dev/null 2>&1; then
86+
echo "Correctly rejected invalid feature"
87+
else
88+
echo "ERROR: Should reject invalid feature" && exit 1
89+
fi
90+
91+
# Test 8: Error handling - invalid profile
92+
echo "Test 8: Error handling for invalid profile"
93+
rm -rf build
94+
if ! "$fpm" run --profile nonexistent --target features_demo > /dev/null 2>&1; then
95+
echo "Correctly rejected invalid profile"
96+
else
97+
echo "ERROR: Should reject invalid profile" && exit 1
98+
fi
99+
100+
# Test 9: Features and profile mutual exclusion
101+
echo "Test 9: Features and profile mutual exclusion"
102+
rm -rf build
103+
if ! "$fpm" run --features debug --profile development --target features_demo > /dev/null 2>&1; then
104+
echo "Correctly rejected features + profile combination"
105+
else
106+
echo "ERROR: Should reject features + profile combination" && exit 1
107+
fi
108+
109+
# Cleanup
110+
rm -rf build output.txt build_list.txt
111+
popd
112+
113+
echo "=== Testing features_with_dependency package ==="
114+
115+
# Test dependency features
116+
pushd "features_with_dependency"
117+
118+
# RE-ENABLE AFTER MERGING fpm WITH CPP PARSING PR
119+
# Test 10: No features - should show NONE for both local and dependency
120+
# echo "Test 10: Dependency package without features"
121+
rm -rf build
122+
#"$fpm" run | tee output.txt
123+
# grep -q "NONE - no local features active" output.txt || { echo "ERROR: Local features NONE message not found"; exit 1; }
124+
# grep -q "Features: NONE" output.txt || { echo "ERROR: Features NONE not found in dependency test"; exit 1; }
125+
# echo "✓ Dependency package baseline works"
126+
127+
# Test 11: Debug dependency feature
128+
echo "Test 11: Debug dependency feature"
129+
rm -rf build
130+
"$fpm" run --features with_feat_debug > output.txt
131+
grep -q "WITH_DEBUG_DEPENDENCY" output.txt || { echo "ERROR: WITH_DEBUG_DEPENDENCY not found"; exit 1; }
132+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled in dependency test"; exit 1; }
133+
echo "✓ Debug dependency feature works"
134+
135+
# Test 12: Release dependency feature
136+
echo "Test 12: Release dependency feature"
137+
rm -rf build
138+
"$fpm" run --features with_feat_release > output.txt
139+
grep -q "WITH_RELEASE_DEPENDENCY" output.txt || { echo "ERROR: WITH_RELEASE_DEPENDENCY not found"; exit 1; }
140+
grep -q "RELEASE mode enabled" output.txt || { echo "ERROR: RELEASE mode not enabled in dependency test"; exit 1; }
141+
echo "✓ Release dependency feature works"
142+
143+
# Test 13: Multi dependency feature
144+
echo "Test 13: Multi dependency feature"
145+
rm -rf build
146+
"$fpm" run --features with_feat_multi > output.txt
147+
grep -q "WITH_MULTI_DEPENDENCY" output.txt || { echo "ERROR: WITH_MULTI_DEPENDENCY not found"; exit 1; }
148+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled in multi dependency test"; exit 1; }
149+
grep -q "MPI support enabled" output.txt || { echo "ERROR: MPI support not enabled in multi dependency test"; exit 1; }
150+
echo "✓ Multi dependency feature works"
151+
152+
# Test 14: Profile with dependency features
153+
echo "Test 14: Debug dependency profile"
154+
rm -rf build
155+
"$fpm" run --profile debug_dep > output.txt
156+
grep -q "WITH_DEBUG_DEPENDENCY" output.txt || { echo "ERROR: WITH_DEBUG_DEPENDENCY not found in profile test"; exit 1; }
157+
grep -q "DEBUG mode enabled" output.txt || { echo "ERROR: DEBUG mode not enabled in dependency profile test"; exit 1; }
158+
echo "✓ Debug dependency profile works"
159+
160+
# Cleanup
161+
rm -rf build output.txt
162+
popd
163+
164+
echo "=== Testing features_per_compiler package ==="
165+
166+
# Test features per compiler package
167+
pushd "features_per_compiler"
168+
169+
# Test 15: Development profile (debug + verbose)
170+
echo "Test 15: Features per compiler - development profile"
171+
rm -rf build
172+
if "$fpm" run --profile development > output.txt 2>&1; then
173+
echo "✓ Exit code 0 (success) as expected"
174+
else
175+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
176+
echo "=== Program output ==="
177+
cat output.txt
178+
echo "======================"
179+
exit 1
180+
fi
181+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
182+
grep -q "✓ DEBUG: debug flags found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
183+
grep -q "✓ VERBOSE: -v flag found" output.txt || { echo "ERROR: Verbose feature not detected"; exit 1; }
184+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
185+
# Check compiler-specific flags (will depend on detected compiler)
186+
if grep -q "Detected compiler: gfortran" output.txt; then
187+
grep -q "✓ Debug: -Wall found" output.txt || { echo "ERROR: gfortran debug flag -Wall not found"; exit 1; }
188+
grep -q "✓ Debug: -fcheck=bounds found" output.txt || { echo "ERROR: gfortran debug flag -fcheck=bounds not found"; exit 1; }
189+
fi
190+
echo "✓ Development profile works"
191+
192+
# Test 16: Production profile (release + fast)
193+
echo "Test 16: Features per compiler - production profile"
194+
rm -rf build
195+
if "$fpm" run --profile production > output.txt 2>&1; then
196+
echo "✓ Exit code 0 (success) as expected"
197+
else
198+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
199+
echo "=== Program output ==="
200+
cat output.txt
201+
echo "======================"
202+
exit 1
203+
fi
204+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
205+
grep -q "✓ RELEASE: -O flags found" output.txt || { echo "ERROR: Release feature not detected"; exit 1; }
206+
grep -q "✓ FAST: fast optimization flags found" output.txt || { echo "ERROR: Fast feature not detected"; exit 1; }
207+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
208+
# Check compiler-specific flags (will depend on detected compiler)
209+
if grep -q "Detected compiler: gfortran" output.txt; then
210+
# Check for -mtune flag (portable tuning flag)
211+
grep -q "✓ Release: -mtune found" output.txt || { echo "ERROR: gfortran release flag -mtune not found"; exit 1; }
212+
grep -q "✓ Fast: -ffast-math found" output.txt || { echo "ERROR: gfortran fast flag -ffast-math not found"; exit 1; }
213+
fi
214+
echo "✓ Production profile works"
215+
216+
# Test 17: Testing profile (debug + strict)
217+
echo "Test 17: Features per compiler - testing profile"
218+
rm -rf build
219+
if "$fpm" run --profile testing > output.txt 2>&1; then
220+
echo "✓ Exit code 0 (success) as expected"
221+
else
222+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
223+
echo "=== Program output ==="
224+
cat output.txt
225+
echo "======================"
226+
exit 1
227+
fi
228+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
229+
grep -q "✓ DEBUG: debug flags found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
230+
grep -q "✓ STRICT: standard compliance flags found" output.txt || { echo "ERROR: Strict feature not detected"; exit 1; }
231+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
232+
# Check compiler-specific flags (will depend on detected compiler)
233+
if grep -q "Detected compiler: gfortran" output.txt; then
234+
grep -q "✓ Strict: -Wpedantic found" output.txt || { echo "ERROR: gfortran strict flag -Wpedantic not found"; exit 1; }
235+
fi
236+
echo "✓ Testing profile works"
237+
238+
# Test 18: Individual features - debug only
239+
echo "Test 18: Features per compiler - debug feature only"
240+
rm -rf build
241+
if "$fpm" run --features debug > output.txt 2>&1; then
242+
echo "✓ Exit code 0 (success) as expected"
243+
else
244+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
245+
echo "=== Program output ==="
246+
cat output.txt
247+
echo "======================"
248+
exit 1
249+
fi
250+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
251+
grep -q "✓ DEBUG: debug flags found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
252+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
253+
# Should NOT have release or fast flags
254+
if grep -q "✓ RELEASE: -O flags found" output.txt; then
255+
echo "ERROR: Release flags should not be present with debug only"
256+
exit 1
257+
fi
258+
echo "✓ Debug feature works"
259+
260+
# Test 19: Individual features - release only
261+
echo "Test 19: Features per compiler - release feature only"
262+
rm -rf build
263+
if "$fpm" run --features release > output.txt 2>&1; then
264+
echo "✓ Exit code 0 (success) as expected"
265+
else
266+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
267+
echo "=== Program output ==="
268+
cat output.txt
269+
echo "======================"
270+
exit 1
271+
fi
272+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
273+
grep -q "✓ RELEASE: -O flags found" output.txt || { echo "ERROR: Release feature not detected"; exit 1; }
274+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
275+
# Should NOT have debug flags
276+
if grep -q "✓ DEBUG: debug flags found" output.txt; then
277+
echo "ERROR: Debug flags should not be present with release only"
278+
exit 1
279+
fi
280+
echo "✓ Release feature works"
281+
282+
# Test 20: No profile/features - baseline
283+
echo "Test 20: Features per compiler - baseline (no profile)"
284+
rm -rf build
285+
if "$fpm" run > output.txt 2>&1; then
286+
echo "✓ Exit code 0 (success) as expected"
287+
else
288+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
289+
echo "=== Program output ==="
290+
cat output.txt
291+
echo "======================"
292+
exit 1
293+
fi
294+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
295+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
296+
# Should NOT have any feature flags in baseline
297+
if grep -q "✓ DEBUG: debug flags found" output.txt; then
298+
echo "ERROR: Debug flags should not be present in baseline"
299+
exit 1
300+
fi
301+
if grep -q "✓ RELEASE: -O flags found" output.txt; then
302+
echo "ERROR: Release flags should not be present in baseline"
303+
exit 1
304+
fi
305+
echo "✓ Baseline (no profile) works"
306+
307+
# Cleanup
308+
rm -rf build output.txt
309+
popd
310+
311+
echo "All FPM features tests passed!"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
program debug_demo
2+
use features_demo
3+
implicit none
4+
5+
write(*,*) 'Debug Demo Program'
6+
write(*,*) '=================='
7+
8+
#ifdef DEBUG
9+
write(*,*) 'Debug mode: ON'
10+
#else
11+
write(*,*) 'Debug mode: OFF'
12+
#endif
13+
14+
call show_features()
15+
16+
end program debug_demo
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
program main
2+
use features_demo
3+
implicit none
4+
5+
call show_features()
6+
7+
write(*,*) ''
8+
write(*,*) get_build_info()
9+
write(*,*) ''
10+
write(*,*) 'Demo completed successfully!'
11+
12+
end program main

0 commit comments

Comments
 (0)