Skip to content

Commit 7a1693b

Browse files
authored
Merge pull request ecmwf#70
Add compiler flag override macro
2 parents b6fc8a6 + 4be34fe commit 7a1693b

File tree

9 files changed

+237
-42
lines changed

9 files changed

+237
-42
lines changed

‎cmake/ecbuild_compiler_flags.cmake‎

Lines changed: 144 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,142 @@ macro( ecbuild_compiler_flags _lang )
7272

7373
endmacro()
7474

75+
##############################################################################
76+
#.rst:
77+
#
78+
# ecbuild_purge_compiler_flags
79+
# ======================
80+
#
81+
# Purge compiler flags for a given language ::
82+
#
83+
# ecbuild_purge_compiler_flags( <lang> )
84+
#
85+
##############################################################################
86+
87+
macro( ecbuild_purge_compiler_flags _lang )
88+
89+
set( options WARN )
90+
set( oneValueArgs "" )
91+
set( multiValueArgs "" )
92+
93+
cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
94+
95+
if( CMAKE_${_lang}_COMPILER_LOADED )
96+
97+
# Clear default compilation flags potentially inherited from parent scope
98+
# when using custom compilation flags
99+
if( ECBUILD_SOURCE_FLAGS OR ECBUILD_COMPILE_FLAGS )
100+
set(CMAKE_${_lang}_FLAGS "")
101+
foreach(_btype ALL RELEASE RELWITHDEBINFO PRODUCTION BIT DEBUG)
102+
set(CMAKE_${_lang}_FLAGS_${_btype} "")
103+
endforeach()
104+
endif()
105+
106+
endif()
107+
108+
if( ${_PAR_WARN} )
109+
ecbuild_warn( "Purging compiler flags set for ${_lang}" )
110+
endif()
111+
112+
endmacro()
113+
114+
##############################################################################
115+
#.rst:
116+
#
117+
# ecbuild_linker_flags
118+
# ====================
119+
#
120+
# Apply user or toolchain specified linker flag overrides per object type (NOT written to cache)
121+
#
122+
# ecbuild_linker_flags()
123+
#
124+
##############################################################################
125+
126+
macro( ecbuild_linker_flags )
127+
foreach( _obj EXE SHARED MODULE )
128+
if( ECBUILD_${_obj}_LINKER_FLAGS )
129+
set( CMAKE_${_obj}_LINKER_FLAGS ${ECBUILD_${_obj}_LINKER_FLAGS} )
130+
endif()
131+
132+
if( NOT "$ENV{LD_RUN_PATH}" EQUAL "" )
133+
set( LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
134+
string( REPLACE ":" ";" LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
135+
foreach( rpath ${LD_RUN_PATH} )
136+
ecbuild_regex_escape( "${rpath}" rpath_escaped )
137+
if( NOT CMAKE_${_obj}_LINKER_FLAGS MATCHES ".*-Wl,-rpath,${rpath_escaped}.*")
138+
set( CMAKE_${_obj}_LINKER_FLAGS "${CMAKE_${_obj}_LINKER_FLAGS} -Wl,-rpath,${rpath}" )
139+
endif()
140+
endforeach()
141+
endif()
142+
endforeach()
143+
144+
foreach( _btype NONE DEBUG BIT PRODUCTION RELEASE RELWITHDEBINFO )
145+
146+
foreach( _obj EXE SHARED MODULE )
147+
if( ECBUILD_${_obj}_LINKER_FLAGS_${_btype} )
148+
set( CMAKE_${_obj}_LINKER_FLAGS_${_btype} ${ECBUILD_${_obj}_LINKER_FLAGS_${_btype}} )
149+
endif()
150+
endforeach()
151+
152+
endforeach()
153+
endmacro()
154+
155+
##############################################################################
156+
#.rst:
157+
#
158+
# ecbuild_override_compiler_flags
159+
# ======================
160+
#
161+
# Purge existing CMAKE_<lang>_FLAGS flags and trigger the use of per source
162+
# file overrideable flags (see ``Using custom compilation flags`` for an
163+
# explanation).
164+
#
165+
# ecbuild_override_compiler_flags()
166+
#
167+
##############################################################################
168+
169+
macro( ecbuild_override_compiler_flags )
170+
171+
set( options "" )
172+
set( oneValueArgs SOURCE_FLAGS COMPILE_FLAGS )
173+
set( multiValueArgs "" )
174+
175+
cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
176+
177+
# Ensure COMPILE/SOURCE_FLAGS is a valid file path
178+
if( DEFINED _PAR_COMPILE_FLAGS AND NOT EXISTS ${_PAR_COMPILE_FLAGS} )
179+
ecbuild_warn( "COMPILE_FLAGS points to non-existent file ${_PAR_COMPILE_FLAGS} and will be ignored" )
180+
unset( ECBUILD_COMPILE_FLAGS )
181+
unset( ECBUILD_COMPILE_FLAGS CACHE )
182+
elseif( DEFINED _PAR_SOURCE_FLAGS AND NOT EXISTS ${_PAR_SOURCE_FLAGS} )
183+
ecbuild_warn( "SOURCE_FLAGS points to non-existent file ${_PAR_SOURCE_FLAGS} and will be ignored" )
184+
unset( ECBUILD_SOURCE_FLAGS )
185+
unset( ECBUILD_SOURCE_FLAGS CACHE )
186+
elseif( DEFINED _PAR_SOURCE_FLAGS OR DEFINED _PAR_COMPILE_FLAGS )
187+
foreach( _lang C CXX Fortran )
188+
if( CMAKE_${_lang}_COMPILER_LOADED )
189+
ecbuild_purge_compiler_flags( ${_lang} WARN )
190+
endif()
191+
endforeach()
192+
193+
if( DEFINED _PAR_COMPILE_FLAGS )
194+
if( DEFINED ECBUILD_COMPILE_FLAGS)
195+
ecbuild_debug( "Override ECBUILD_COMPILE_FLAGS (${ECBUILD_COMPILE_FLAGS}) with ${_PAR_COMPILE_FLAGS}" )
196+
endif()
197+
set( ECBUILD_COMPILE_FLAGS ${_PAR_COMPILE_FLAGS} )
198+
include( ${ECBUILD_COMPILE_FLAGS} )
199+
elseif( DEFINED _PAR_SOURCE_FLAGS )
200+
if( DEFINED ECBUILD_SOURCE_FLAGS)
201+
ecbuild_debug( "Override ECBUILD_SOURCE_FLAGS (${ECBUILD_SOURCE_FLAGS}) with ${_PAR_SOURCE_FLAGS}" )
202+
endif()
203+
set( ECBUILD_SOURCE_FLAGS ${_PAR_SOURCE_FLAGS} )
204+
endif()
205+
206+
ecbuild_linker_flags()
207+
endif()
208+
209+
endmacro()
210+
75211
##############################################################################
76212
#.rst:
77213
#
@@ -172,59 +308,25 @@ foreach( _flags COMPILE SOURCE )
172308
endif()
173309
set( ECBUILD_${_flags}_FLAGS ${${PROJECT_NAME_CAPS}_ECBUILD_${_flags}_FLAGS} )
174310
endif()
175-
# Ensure ECBUILD_${_flags}_FLAGS is a valid file path
176-
if( DEFINED ECBUILD_${_flags}_FLAGS AND NOT EXISTS ${ECBUILD_${_flags}_FLAGS} )
177-
ecbuild_warn( "ECBUILD_${_flags}_FLAGS points to non-existent file ${ECBUILD_${_flags}_FLAGS} and will be ignored" )
178-
unset( ECBUILD_${_flags}_FLAGS )
179-
unset( ECBUILD_${_flags}_FLAGS CACHE )
180-
endif()
181311
endforeach()
182-
if( ECBUILD_COMPILE_FLAGS )
183-
include( "${ECBUILD_COMPILE_FLAGS}" )
312+
if( DEFINED ECBUILD_COMPILE_FLAGS )
313+
ecbuild_override_compiler_flags( COMPILE_FLAGS ${ECBUILD_COMPILE_FLAGS} )
314+
elseif( DEFINED ECBUILD_SOURCE_FLAGS )
315+
ecbuild_override_compiler_flags( SOURCE_FLAGS ${ECBUILD_SOURCE_FLAGS} )
184316
endif()
185317

186318
foreach( _lang C CXX Fortran )
187319
if( CMAKE_${_lang}_COMPILER_LOADED )
188320

189-
# Clear default compilation flags potentially inherited from parent scope
190-
# when using custom compilation flags
191-
if( ECBUILD_SOURCE_FLAGS OR ECBUILD_COMPILE_FLAGS )
192-
set(CMAKE_${_lang}_FLAGS "")
193-
foreach(_btype ALL RELEASE RELWITHDEBINFO PRODUCTION BIT DEBUG)
194-
set(CMAKE_${_lang}_FLAGS_${_btype} "")
195-
endforeach()
196321
# Load default compilation flags only if custom compilation flags not enabled
197-
else()
322+
if( NOT (DEFINED ECBUILD_SOURCE_FLAGS OR DEFINED ECBUILD_COMPILE_FLAGS) )
198323
ecbuild_compiler_flags( ${_lang} )
199324
endif()
200325

201326
endif()
202327
endforeach()
203328

204-
# Apply user or toolchain specified linker flag overrides per object type (NOT written to cache)
205-
foreach( _obj EXE SHARED MODULE )
206-
if( ECBUILD_${_obj}_LINKER_FLAGS )
207-
set( CMAKE_${_obj}_LINKER_FLAGS ${ECBUILD_${_obj}_LINKER_FLAGS} )
208-
endif()
209-
210-
if( NOT "$ENV{LD_RUN_PATH}" EQUAL "" )
211-
set( LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
212-
string( REPLACE ":" ";" LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
213-
foreach( rpath ${LD_RUN_PATH} )
214-
ecbuild_regex_escape( "${rpath}" rpath_escaped )
215-
if( NOT CMAKE_${_obj}_LINKER_FLAGS MATCHES ".*-Wl,-rpath,${rpath_escaped}.*")
216-
set( CMAKE_${_obj}_LINKER_FLAGS "${CMAKE_${_obj}_LINKER_FLAGS} -Wl,-rpath,${rpath}" )
217-
endif()
218-
endforeach()
219-
endif()
220-
endforeach()
221-
222-
foreach( _btype NONE DEBUG BIT PRODUCTION RELEASE RELWITHDEBINFO )
223-
224-
foreach( _obj EXE SHARED MODULE )
225-
if( ECBUILD_${_obj}_LINKER_FLAGS_${_btype} )
226-
set( CMAKE_${_obj}_LINKER_FLAGS_${_btype} ${ECBUILD_${_obj}_LINKER_FLAGS_${_btype}} )
227-
endif()
228-
endforeach()
329+
if( NOT DEFINED ECBUILD_COMPILE_FLAGS AND NOT DEFINED ECBUILD_SOURCE_FLAGS )
330+
ecbuild_linker_flags()
331+
endif()
229332

230-
endforeach()

‎tests/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ add_subdirectory( ecbuild_shared_libs )
1111
add_subdirectory( interface_library )
1212
add_subdirectory( project_import )
1313
add_subdirectory( project_summary )
14+
add_subdirectory( ecbuild_override_compiler_flags )
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(_dir ${CMAKE_CURRENT_BINARY_DIR})
2+
configure_file(run-test.sh.in ${_dir}/run-test.sh @ONLY)
3+
configure_file(test_ecbuild_override_compiler_flags.cmake ${_dir}/CMakeLists.txt COPYONLY)
4+
configure_file(emptyfile.c ${_dir}/emptyfile.c COPYONLY)
5+
configure_file(emptyfile.cxx ${_dir}/emptyfile.cxx COPYONLY)
6+
configure_file(emptyfile.F90 ${_dir}/emptyfile.F90 COPYONLY)
7+
configure_file(compiler_flags.cmake ${_dir}/compiler_flags.cmake COPYONLY)
8+
9+
ecbuild_add_test(
10+
TARGET test_ecbuild_override_compiler_flags
11+
TYPE SCRIPT
12+
COMMAND run-test.sh
13+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
set( OVERRIDECOMPILERFLAGS_C_FLAGS "-g -fPIC" )
2+
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS "-g -fPIC" )
3+
set( OVERRIDECOMPILERFLAGS_Fortran_FLAGS "-g -fortran_only_flag" )
4+
5+
set( OVERRIDECOMPILERFLAGS_C_FLAGS_DEBUG "-O0" )
6+
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS_DEBUG "-O0" )
7+
8+
set( OVERRIDECOMPILERFLAGS_C_FLAGS_BIT "-O2" )
9+
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS_BIT "-O2" )
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
! An empty file
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// An empty file
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// An empty file
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
HERE="$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd -P )"
6+
7+
cd $HERE
8+
9+
rm -rf build # cleanup
10+
mkdir build
11+
cd build
12+
13+
cmake -DCMAKE_MODULE_PATH=@ECBUILD_MACROS_DIR@ -DECBUILD_LOG_LEVEL=DEBUG -DCMAKE_BUILD_TYPE=BIT -DECBUILD_SOURCE_FLAGS=@CMAKE_CURRENT_SOURCE_DIR@/flags-sourceflags.json ..
14+
15+
cd ..
16+
17+
rm -rf build # cleanup
18+
mkdir build
19+
cd build
20+
21+
cmake -DCMAKE_MODULE_PATH=@ECBUILD_MACROS_DIR@ -DECBUILD_LOG_LEVEL=DEBUG -DCMAKE_BUILD_TYPE=DEBUG -DECBUILD_SOURCE_FLAGS=@CMAKE_CURRENT_SOURCE_DIR@/flags-sourceflags.json ..
22+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
cmake_minimum_required( VERSION 3.12 FATAL_ERROR )
2+
3+
find_package( ecbuild 3.6 REQUIRED )
4+
5+
project(OverrideCompilerFlags VERSION 1.0 LANGUAGES C CXX Fortran)
6+
7+
ecbuild_override_compiler_flags( COMPILE_FLAGS compiler_flags.cmake )
8+
9+
ecbuild_add_library(
10+
TARGET overrideflags
11+
SOURCES emptyfile.c emptyfile.cxx emptyfile.F90
12+
)
13+
14+
get_property( _flags SOURCE emptyfile.c PROPERTY COMPILE_FLAGS )
15+
if( CMAKE_BUILD_TYPE MATCHES BIT )
16+
if( NOT ${_flags} MATCHES "-g -fPIC -O2" )
17+
message(${_flags})
18+
message(FATAL_ERROR "Incorrect BIT flags for emptyfile.c")
19+
endif()
20+
elseif( CMAKE_BUILD_TYPE MATCHES DEBUG )
21+
if( NOT ${_flags} MATCHES "-g -fPIC -O0" )
22+
message(${_flags})
23+
message(FATAL_ERROR "Incorrect DEBUG flags for emptyfile.c")
24+
endif()
25+
endif()
26+
27+
get_property( _flags SOURCE emptyfile.cxx PROPERTY COMPILE_FLAGS )
28+
if( CMAKE_BUILD_TYPE MATCHES BIT )
29+
if( NOT ${_flags} MATCHES "-g -fPIC -O2" )
30+
message(${_flags})
31+
message(FATAL_ERROR "Incorrect BIT flags for emptyfile.cxx")
32+
endif()
33+
elseif( CMAKE_BUILD_TYPE MATCHES DEBUG )
34+
if( NOT ${_flags} MATCHES "-g -fPIC -O0" )
35+
message(${_flags})
36+
message(FATAL_ERROR "Incorrect DEBUG flags for emptyfile.cxx")
37+
endif()
38+
endif()
39+
40+
get_property( _flags SOURCE emptyfile.F90 PROPERTY COMPILE_FLAGS )
41+
if( NOT ${_flags} MATCHES "-g -fortran_only_flag" )
42+
message(${_flags})
43+
message(FATAL_ERROR "Incorrect flags for emptyfile.F90")
44+
endif()
45+

0 commit comments

Comments
 (0)