Skip to content

Commit acb7f34

Browse files
committed
example package: features_per_compiler
1 parent f556321 commit acb7f34

File tree

4 files changed

+401
-0
lines changed

4 files changed

+401
-0
lines changed

ci/test_features.sh

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,136 @@ echo "✓ Debug dependency profile works"
161161
rm -rf build output.txt
162162
popd
163163

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 | tee output.txt; 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+
exit 1
177+
fi
178+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
179+
grep -q "✓ DEBUG: -g flag found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
180+
grep -q "✓ VERBOSE: -v flag found" output.txt || { echo "ERROR: Verbose feature not detected"; exit 1; }
181+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
182+
# Check compiler-specific flags (will depend on detected compiler)
183+
if grep -q "Detected compiler: gfortran" output.txt; then
184+
grep -q "✓ Debug: -Wall found" output.txt || { echo "ERROR: gfortran debug flag -Wall not found"; exit 1; }
185+
grep -q "✓ Debug: -fcheck=bounds found" output.txt || { echo "ERROR: gfortran debug flag -fcheck=bounds not found"; exit 1; }
186+
fi
187+
echo "✓ Development profile works"
188+
189+
# Test 16: Production profile (release + fast)
190+
echo "Test 16: Features per compiler - production profile"
191+
rm -rf build
192+
if "$fpm" run --profile production | tee output.txt; then
193+
echo "✓ Exit code 0 (success) as expected"
194+
else
195+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
196+
exit 1
197+
fi
198+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
199+
grep -q "✓ RELEASE: -O flags found" output.txt || { echo "ERROR: Release feature not detected"; exit 1; }
200+
grep -q "✓ FAST: fast optimization flags found" output.txt || { echo "ERROR: Fast feature not detected"; exit 1; }
201+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
202+
# Check compiler-specific flags (will depend on detected compiler)
203+
if grep -q "Detected compiler: gfortran" output.txt; then
204+
# Check for either -march=native or -mcpu (Apple Silicon uses -mcpu)
205+
if ! (grep -q "✓ Release: -march=native found" output.txt || grep -q "✓ Release: -mcpu found" output.txt); then
206+
echo "ERROR: gfortran release architecture flag (-march=native or -mcpu) not found"
207+
exit 1
208+
fi
209+
grep -q "✓ Fast: -Ofast found" output.txt || { echo "ERROR: gfortran fast flag -Ofast not found"; exit 1; }
210+
fi
211+
echo "✓ Production profile works"
212+
213+
# Test 17: Testing profile (debug + strict)
214+
echo "Test 17: Features per compiler - testing profile"
215+
rm -rf build
216+
if "$fpm" run --profile testing | tee output.txt; then
217+
echo "✓ Exit code 0 (success) as expected"
218+
else
219+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
220+
exit 1
221+
fi
222+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
223+
grep -q "✓ DEBUG: -g flag found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
224+
grep -q "✓ STRICT: standard compliance flags found" output.txt || { echo "ERROR: Strict feature not detected"; exit 1; }
225+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
226+
# Check compiler-specific flags (will depend on detected compiler)
227+
if grep -q "Detected compiler: gfortran" output.txt; then
228+
grep -q "✓ Strict: -Wpedantic found" output.txt || { echo "ERROR: gfortran strict flag -Wpedantic not found"; exit 1; }
229+
fi
230+
echo "✓ Testing profile works"
231+
232+
# Test 18: Individual features - debug only
233+
echo "Test 18: Features per compiler - debug feature only"
234+
rm -rf build
235+
if "$fpm" run --features debug | tee output.txt; then
236+
echo "✓ Exit code 0 (success) as expected"
237+
else
238+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
239+
exit 1
240+
fi
241+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
242+
grep -q "✓ DEBUG: -g flag found" output.txt || { echo "ERROR: Debug feature not detected"; exit 1; }
243+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
244+
# Should NOT have release or fast flags
245+
if grep -q "✓ RELEASE: -O flags found" output.txt; then
246+
echo "ERROR: Release flags should not be present with debug only"
247+
exit 1
248+
fi
249+
echo "✓ Debug feature works"
250+
251+
# Test 19: Individual features - release only
252+
echo "Test 19: Features per compiler - release feature only"
253+
rm -rf build
254+
if "$fpm" run --features release | tee output.txt; then
255+
echo "✓ Exit code 0 (success) as expected"
256+
else
257+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
258+
exit 1
259+
fi
260+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
261+
grep -q "✓ RELEASE: -O flags found" output.txt || { echo "ERROR: Release feature not detected"; exit 1; }
262+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
263+
# Should NOT have debug flags
264+
if grep -q "✓ DEBUG: -g flag found" output.txt; then
265+
echo "ERROR: Debug flags should not be present with release only"
266+
exit 1
267+
fi
268+
echo "✓ Release feature works"
269+
270+
# Test 20: No profile/features - baseline
271+
echo "Test 20: Features per compiler - baseline (no profile)"
272+
rm -rf build
273+
if "$fpm" run | tee output.txt; then
274+
echo "✓ Exit code 0 (success) as expected"
275+
else
276+
echo "ERROR: Expected exit code 0 but got non-zero exit code"
277+
exit 1
278+
fi
279+
grep -q "Features Per Compiler Demo" output.txt || { echo "ERROR: Features Per Compiler Demo not found"; exit 1; }
280+
grep -q "✓ All compiler flag checks PASSED" output.txt || { echo "ERROR: Expected all checks to pass"; exit 1; }
281+
# Should NOT have any feature flags in baseline
282+
if grep -q "✓ DEBUG: -g flag found" output.txt; then
283+
echo "ERROR: Debug flags should not be present in baseline"
284+
exit 1
285+
fi
286+
if grep -q "✓ RELEASE: -O flags found" output.txt; then
287+
echo "ERROR: Release flags should not be present in baseline"
288+
exit 1
289+
fi
290+
echo "✓ Baseline (no profile) works"
291+
292+
# Cleanup
293+
rm -rf build output.txt
294+
popd
295+
164296
echo "All FPM features tests passed!"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
output.txt
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
program main
2+
use iso_fortran_env, only: compiler_options
3+
implicit none
4+
5+
character(len=:), allocatable :: options_str
6+
character(len=20) :: detected_compiler
7+
logical :: debug_active, release_active, verbose_active, fast_active, strict_active
8+
logical :: all_checks_passed
9+
integer :: failed_checks
10+
11+
! Get compiler flags used to build this file
12+
options_str = compiler_options()
13+
14+
! Display compiler information
15+
print '(a)', '================================='
16+
print '(a)', 'Features Per Compiler Demo'
17+
print '(a)', '================================='
18+
print '(a)', ''
19+
20+
! Detect compiler type using the function
21+
detected_compiler = compiled_with()
22+
23+
print '(2a)', 'Detected compiler: ', detected_compiler
24+
print '(a)', ''
25+
print '(2a)', 'Compiler options: ', trim(options_str)
26+
print '(a)', ''
27+
28+
! Check for feature flags
29+
debug_active = index(options_str, '-g') > 0
30+
release_active = index(options_str, '-O') > 0
31+
verbose_active = index(options_str, ' -v') > 0 .or. index(options_str, ' -v ') > 0
32+
fast_active = index(options_str, '-Ofast') > 0 .or. index(options_str, '-fast') > 0
33+
strict_active = index(options_str, '-std=f2018') > 0 .or. index(options_str, '-stand f18') > 0
34+
35+
! Display active features
36+
print '(a)', 'Active features detected:'
37+
if (debug_active) print '(a)', ' ✓ DEBUG: -g flag found'
38+
if (release_active) print '(a)', ' ✓ RELEASE: -O flags found'
39+
if (verbose_active) print '(a)', ' ✓ VERBOSE: -v flag found'
40+
if (fast_active) print '(a)', ' ✓ FAST: fast optimization flags found'
41+
if (strict_active) print '(a)', ' ✓ STRICT: standard compliance flags found'
42+
43+
print '(a)', ''
44+
45+
! Check compiler-specific flags and validate
46+
failed_checks = check_compiler_flags(detected_compiler, options_str, debug_active, release_active, fast_active, strict_active)
47+
48+
print '(a)', ''
49+
50+
! Determine overall result
51+
all_checks_passed = (failed_checks == 0)
52+
53+
if (all_checks_passed) then
54+
print '(a)', '✓ All compiler flag checks PASSED'
55+
print '(a)', ''
56+
else
57+
print '(a,i0,a)', '', failed_checks, ' compiler flag checks FAILED'
58+
print '(a)', ''
59+
end if
60+
61+
! Exit with appropriate code
62+
stop merge(0,1,all_checks_passed)
63+
64+
contains
65+
66+
function check_compiler_flags(compiler, options, debug_on, release_on, fast_on, strict_on) result(failed_count)
67+
character(len=*), intent(in) :: compiler, options
68+
logical, intent(in) :: debug_on, release_on, fast_on, strict_on
69+
integer :: failed_count
70+
71+
failed_count = 0
72+
select case (compiler)
73+
case ('gfortran')
74+
failed_count = check_gfortran_flags(options, debug_on, release_on, fast_on, strict_on)
75+
case ('ifort')
76+
failed_count = check_ifort_flags(options, debug_on, release_on, fast_on, strict_on)
77+
case ('ifx')
78+
failed_count = check_ifx_flags(options, debug_on, release_on, fast_on, strict_on)
79+
case default
80+
print '(a)', 'Compiler-specific checks: Unknown compiler - only base flags checked'
81+
end select
82+
end function
83+
84+
function check_flag(options, flag_name, feature_name, description) result(found)
85+
character(len=*), intent(in) :: options, flag_name, feature_name, description
86+
logical :: found
87+
88+
found = index(options, flag_name) > 0
89+
if (found) then
90+
print '(a,a,a,a,a)', '', feature_name, ': ', description, ' found'
91+
else
92+
print '(a,a,a,a,a)', '', feature_name, ': ', description, ' NOT found'
93+
end if
94+
end function
95+
96+
function compiled_with() result(msg)
97+
use iso_fortran_env, only: compiler_version
98+
character(len=:), allocatable :: msg
99+
character(len=:), allocatable :: version_str
100+
101+
version_str = compiler_version()
102+
103+
if (index(version_str, 'GCC') > 0) then
104+
msg = 'gfortran'
105+
else if (index(version_str, 'Classic') > 0) then
106+
msg = 'ifort'
107+
else if (index(version_str, 'Intel') > 0) then
108+
msg = 'ifx'
109+
else
110+
msg = 'any'
111+
end if
112+
end function
113+
114+
function check_gfortran_flags(options, debug_on, release_on, fast_on, strict_on) result(failed_count)
115+
character(len=*), intent(in) :: options
116+
logical, intent(in) :: debug_on, release_on, fast_on, strict_on
117+
integer :: failed_count
118+
119+
failed_count = 0
120+
print '(a)', 'Compiler-specific flag checks (gfortran):'
121+
122+
if (debug_on) then
123+
if (.not. check_flag(options, '-Wall', 'Debug', '-Wall')) failed_count = failed_count + 1
124+
if (.not. check_flag(options, '-Wextra', 'Debug', '-Wextra')) failed_count = failed_count + 1
125+
if (.not. check_flag(options, '-fcheck=bounds', 'Debug', '-fcheck=bounds')) failed_count = failed_count + 1
126+
if (.not. check_flag(options, '-fbacktrace', 'Debug', '-fbacktrace')) failed_count = failed_count + 1
127+
end if
128+
129+
if (release_on) then
130+
! Check for either -march=native or -mcpu (Apple Silicon uses -mcpu)
131+
if (.not. (index(options, '-march=native') > 0 .or. index(options, '-mcpu') > 0)) then
132+
print '(a)', ' ✗ Release: neither -march=native nor -mcpu found'
133+
failed_count = failed_count + 1
134+
else
135+
if (index(options, '-march=native') > 0) then
136+
print '(a)', ' ✓ Release: -march=native found'
137+
else
138+
print '(a)', ' ✓ Release: -mcpu found'
139+
end if
140+
end if
141+
if (.not. check_flag(options, '-funroll-loops', 'Release', '-funroll-loops')) failed_count = failed_count + 1
142+
end if
143+
144+
if (fast_on) then
145+
if (.not. check_flag(options, '-Ofast', 'Fast', '-Ofast')) failed_count = failed_count + 1
146+
if (.not. check_flag(options, '-ffast-math', 'Fast', '-ffast-math')) failed_count = failed_count + 1
147+
end if
148+
149+
if (strict_on) then
150+
if (.not. check_flag(options, '-Wpedantic', 'Strict', '-Wpedantic')) failed_count = failed_count + 1
151+
if (.not. check_flag(options, '-Werror', 'Strict', '-Werror')) failed_count = failed_count + 1
152+
end if
153+
end function
154+
155+
function check_ifort_flags(options, debug_on, release_on, fast_on, strict_on) result(failed_count)
156+
character(len=*), intent(in) :: options
157+
logical, intent(in) :: debug_on, release_on, fast_on, strict_on
158+
integer :: failed_count
159+
160+
failed_count = 0
161+
print '(a)', 'Compiler-specific flag checks (ifort):'
162+
163+
if (debug_on) then
164+
if (.not. check_flag(options, '-warn all', 'Debug', '-warn all')) failed_count = failed_count + 1
165+
if (.not. check_flag(options, '-check bounds', 'Debug', '-check bounds')) failed_count = failed_count + 1
166+
if (.not. check_flag(options, '-traceback', 'Debug', '-traceback')) failed_count = failed_count + 1
167+
end if
168+
169+
if (release_on) then
170+
if (.not. check_flag(options, '-xHost', 'Release', '-xHost')) failed_count = failed_count + 1
171+
if (.not. check_flag(options, '-unroll', 'Release', '-unroll')) failed_count = failed_count + 1
172+
end if
173+
174+
if (fast_on) then
175+
if (.not. check_flag(options, '-fast', 'Fast', '-fast')) failed_count = failed_count + 1
176+
end if
177+
178+
if (strict_on) then
179+
if (.not. check_flag(options, '-stand f18', 'Strict', '-stand f18')) failed_count = failed_count + 1
180+
if (.not. check_flag(options, '-warn errors', 'Strict', '-warn errors')) failed_count = failed_count + 1
181+
end if
182+
end function
183+
184+
function check_ifx_flags(options, debug_on, release_on, fast_on, strict_on) result(failed_count)
185+
character(len=*), intent(in) :: options
186+
logical, intent(in) :: debug_on, release_on, fast_on, strict_on
187+
integer :: failed_count
188+
189+
failed_count = 0
190+
print '(a)', 'Compiler-specific flag checks (ifx):'
191+
192+
if (debug_on) then
193+
if (.not. check_flag(options, '-warn all', 'Debug', '-warn all')) failed_count = failed_count + 1
194+
if (.not. check_flag(options, '-check bounds', 'Debug', '-check bounds')) failed_count = failed_count + 1
195+
if (.not. check_flag(options, '-traceback', 'Debug', '-traceback')) failed_count = failed_count + 1
196+
end if
197+
198+
if (release_on) then
199+
if (.not. check_flag(options, '-xHost', 'Release', '-xHost')) failed_count = failed_count + 1
200+
if (.not. check_flag(options, '-unroll', 'Release', '-unroll')) failed_count = failed_count + 1
201+
end if
202+
203+
if (fast_on) then
204+
if (.not. check_flag(options, '-fast', 'Fast', '-fast')) failed_count = failed_count + 1
205+
end if
206+
207+
if (strict_on) then
208+
if (.not. check_flag(options, '-stand f18', 'Strict', '-stand f18')) failed_count = failed_count + 1
209+
if (.not. check_flag(options, '-warn errors', 'Strict', '-warn errors')) failed_count = failed_count + 1
210+
end if
211+
end function
212+
213+
end program main

0 commit comments

Comments
 (0)