Skip to content

Commit

Permalink
Add ecbuild_override_compiler_flags macro
Browse files Browse the repository at this point in the history
  • Loading branch information
awnawab committed Oct 31, 2024
1 parent 56af6a6 commit c4acdc0
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 64 deletions.
158 changes: 94 additions & 64 deletions cmake/ecbuild_compiler_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -111,38 +111,99 @@ macro( ecbuild_purge_compiler_flags _lang )

endmacro()

macro( ecbuild_init_overrideable_compiler_flags )
##############################################################################
#.rst:
#
# ecbuild_linker_flags
# ====================
#
# Apply user or toolchain specified linker flag overrides per object type (NOT written to cache)
#
# ecbuild_linker_flags()
#
##############################################################################

macro( ecbuild_linker_flags )
foreach( _obj EXE SHARED MODULE )
if( ECBUILD_${_obj}_LINKER_FLAGS )
set( CMAKE_${_obj}_LINKER_FLAGS ${ECBUILD_${_obj}_LINKER_FLAGS} )
endif()

if( NOT "$ENV{LD_RUN_PATH}" EQUAL "" )
set( LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
string( REPLACE ":" ";" LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
foreach( rpath ${LD_RUN_PATH} )
ecbuild_regex_escape( "${rpath}" rpath_escaped )
if( NOT CMAKE_${_obj}_LINKER_FLAGS MATCHES ".*-Wl,-rpath,${rpath_escaped}.*")
set( CMAKE_${_obj}_LINKER_FLAGS "${CMAKE_${_obj}_LINKER_FLAGS} -Wl,-rpath,${rpath}" )
endif()
endforeach()
endif()
endforeach()

foreach( _btype NONE DEBUG BIT PRODUCTION RELEASE RELWITHDEBINFO )

foreach( _obj EXE SHARED MODULE )
if( ECBUILD_${_obj}_LINKER_FLAGS_${_btype} )
set( CMAKE_${_obj}_LINKER_FLAGS_${_btype} ${ECBUILD_${_obj}_LINKER_FLAGS_${_btype}} )
endif()
endforeach()

endforeach()
endmacro()

##############################################################################
#.rst:
#
# ecbuild_override_compiler_flags
# ======================
#
# Purge existing CMAKE_<lang>_FLAGS flags and trigger the use of per source
# file overrideable flags (see ``Using custom compilation flags`` for an
# explanation).
#
# ecbuild_override_compiler_flags()
#
##############################################################################

set( options CAPTURE_BUNDLE_FLAGS )
macro( ecbuild_override_compiler_flags )

set( options "" )
set( oneValueArgs SOURCE_FLAGS COMPILE_FLAGS )
set( multiValueArgs LANGUAGES )
set( multiValueArgs "" )

cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

foreach(_lang ${_PAR_LANGUAGES} )
ecbuild_purge_compiler_flags( ${_lang} WARN )
endforeach()

if( ${_PAR_CAPTURE_BUNDLE_FLAGS} )
foreach(_lang ${_PAR_LANGUAGES} )
set( ${PNAME}_${_lang}_FLAGS "${${PNAME}_${_lang}_FLAGS} ${ECBUILD_${_lang}_FLAGS}" )
foreach(_btype ALL RELEASE RELWITHDEBINFO PRODUCTION BIT DEBUG)
set( ${PNAME}_${_lang}_FLAGS_${_btype} "${${PNAME}_${_lang}_FLAGS_${_btype}} ${ECBUILD_${_lang}_FLAGS_${_btype}}" )
endforeach()
# Ensure COMPILE/SOURCE_FLAGS is a valid file path
if( DEFINED _PAR_COMPILE_FLAGS AND NOT EXISTS ${_PAR_COMPILE_FLAGS} )
ecbuild_warn( "COMPILE_FLAGS points to non-existent file ${_PAR_COMPILE_FLAGS} and will be ignored" )
unset( ECBUILD_COMPILE_FLAGS )
unset( ECBUILD_COMPILE_FLAGS CACHE )
elseif( DEFINED _PAR_SOURCE_FLAGS AND NOT EXISTS ${_PAR_SOURCE_FLAGS} )
ecbuild_warn( "SOURCE_FLAGS points to non-existent file ${_PAR_SOURCE_FLAGS} and will be ignored" )
unset( ECBUILD_SOURCE_FLAGS )
unset( ECBUILD_SOURCE_FLAGS CACHE )
elseif( DEFINED _PAR_SOURCE_FLAGS OR DEFINED _PAR_COMPILE_FLAGS )
foreach( _lang C CXX Fortran )
if( CMAKE_${_lang}_COMPILER_LOADED )
ecbuild_purge_compiler_flags( ${_lang} WARN )
endif()
endforeach()
endif()

if( DEFINED _PAR_COMPILE_FLAGS )
if( DEFINED ECBUILD_COMPILE_FLAGS)
ecbuild_debug( "Override ECBUILD_COMPILE_FLAGS (${ECBUILD_COMPILE_FLAGS}) with ${_PAR_COMPILE_FLAGS}" )
endif()
set( ECBUILD_COMPILE_FLAGS ${_PAR_COMPILE_FLAGS} )
include( ${ECBUILD_COMPILE_FLAGS} )
elseif( DEFINED _PAR_SOURCE_FLAGS )
if( DEFINED ECBUILD_SOURCE_FLAGS)
ecbuild_debug( "Override ECBUILD_SOURCE_FLAGS (${ECBUILD_SOURCE_FLAGS}) with ${_PAR_SOURCE_FLAGS}" )

if( DEFINED _PAR_COMPILE_FLAGS )
if( DEFINED ECBUILD_COMPILE_FLAGS)
ecbuild_debug( "Override ECBUILD_COMPILE_FLAGS (${ECBUILD_COMPILE_FLAGS}) with ${_PAR_COMPILE_FLAGS}" )
endif()
set( ECBUILD_COMPILE_FLAGS ${_PAR_COMPILE_FLAGS} )
include( ${ECBUILD_COMPILE_FLAGS} )
elseif( DEFINED _PAR_SOURCE_FLAGS )
if( DEFINED ECBUILD_SOURCE_FLAGS)
ecbuild_debug( "Override ECBUILD_SOURCE_FLAGS (${ECBUILD_SOURCE_FLAGS}) with ${_PAR_SOURCE_FLAGS}" )
endif()
set( ECBUILD_SOURCE_FLAGS ${_PAR_SOURCE_FLAGS} )
endif()
set( ECBUILD_SOURCE_FLAGS ${_PAR_SOURCE_FLAGS} )

ecbuild_linker_flags()
endif()

endmacro()
Expand Down Expand Up @@ -247,56 +308,25 @@ foreach( _flags COMPILE SOURCE )
endif()
set( ECBUILD_${_flags}_FLAGS ${${PROJECT_NAME_CAPS}_ECBUILD_${_flags}_FLAGS} )
endif()
# Ensure ECBUILD_${_flags}_FLAGS is a valid file path
if( DEFINED ECBUILD_${_flags}_FLAGS AND NOT EXISTS ${ECBUILD_${_flags}_FLAGS} )
ecbuild_warn( "ECBUILD_${_flags}_FLAGS points to non-existent file ${ECBUILD_${_flags}_FLAGS} and will be ignored" )
unset( ECBUILD_${_flags}_FLAGS )
unset( ECBUILD_${_flags}_FLAGS CACHE )
endif()
endforeach()
if( ECBUILD_COMPILE_FLAGS )
include( "${ECBUILD_COMPILE_FLAGS}" )
if( DEFINED ECBUILD_COMPILE_FLAGS )
ecbuild_override_compiler_flags( COMPILE_FLAGS ${ECBUILD_COMPILE_FLAGS} )
elseif( DEFINED ECBUILD_SOURCE_FLAGS )
ecbuild_override_compiler_flags( SOURCE_FLAGS ${ECBUILD_SOURCE_FLAGS} )
endif()

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

# Clear default compilation flags potentially inherited from parent scope
# when using custom compilation flags
if( ECBUILD_SOURCE_FLAGS OR ECBUILD_COMPILE_FLAGS )
ecbuild_purge_compiler_flags( ${_lang} )
# Load default compilation flags only if custom compilation flags not enabled
else()
if( NOT (DEFINED ECBUILD_SOURCE_FLAGS OR DEFINED ECBUILD_COMPILE_FLAGS) )
ecbuild_compiler_flags( ${_lang} )
endif()

endif()
endforeach()

# Apply user or toolchain specified linker flag overrides per object type (NOT written to cache)
foreach( _obj EXE SHARED MODULE )
if( ECBUILD_${_obj}_LINKER_FLAGS )
set( CMAKE_${_obj}_LINKER_FLAGS ${ECBUILD_${_obj}_LINKER_FLAGS} )
endif()

if( NOT "$ENV{LD_RUN_PATH}" EQUAL "" )
set( LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
string( REPLACE ":" ";" LD_RUN_PATH "$ENV{LD_RUN_PATH}" )
foreach( rpath ${LD_RUN_PATH} )
ecbuild_regex_escape( "${rpath}" rpath_escaped )
if( NOT CMAKE_${_obj}_LINKER_FLAGS MATCHES ".*-Wl,-rpath,${rpath_escaped}.*")
set( CMAKE_${_obj}_LINKER_FLAGS "${CMAKE_${_obj}_LINKER_FLAGS} -Wl,-rpath,${rpath}" )
endif()
endforeach()
endif()
endforeach()

foreach( _btype NONE DEBUG BIT PRODUCTION RELEASE RELWITHDEBINFO )

foreach( _obj EXE SHARED MODULE )
if( ECBUILD_${_obj}_LINKER_FLAGS_${_btype} )
set( CMAKE_${_obj}_LINKER_FLAGS_${_btype} ${ECBUILD_${_obj}_LINKER_FLAGS_${_btype}} )
endif()
endforeach()
if( NOT DEFINED ECBUILD_COMPILE_FLAGS AND NOT DEFINED ECBUILD_SOURCE_FLAGS )
ecbuild_linker_flags()
endif()

endforeach()
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ add_subdirectory( find_ecbuild )
add_subdirectory( project_import )
add_subdirectory( ecbuild_shared_libs )
add_subdirectory( interface_library )
add_subdirectory( ecbuild_override_compiler_flags )
13 changes: 13 additions & 0 deletions tests/ecbuild_override_compiler_flags/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set(_dir ${CMAKE_CURRENT_BINARY_DIR})
configure_file(run-test.sh.in ${_dir}/run-test.sh @ONLY)
configure_file(test_ecbuild_override_compiler_flags.cmake ${_dir}/CMakeLists.txt COPYONLY)
configure_file(emptyfile.c ${_dir}/emptyfile.c COPYONLY)
configure_file(emptyfile.cxx ${_dir}/emptyfile.cxx COPYONLY)
configure_file(emptyfile.F90 ${_dir}/emptyfile.F90 COPYONLY)
configure_file(compiler_flags.cmake ${_dir}/compiler_flags.cmake COPYONLY)

ecbuild_add_test(
TARGET test_ecbuild_override_compiler_flags
TYPE SCRIPT
COMMAND run-test.sh
)
9 changes: 9 additions & 0 deletions tests/ecbuild_override_compiler_flags/compiler_flags.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
set( OVERRIDECOMPILERFLAGS_C_FLAGS "-g -fPIC" )
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS "-g -fPIC" )
set( OVERRIDECOMPILERFLAGS_Fortran_FLAGS "-g -fortran_only_flag" )

set( OVERRIDECOMPILERFLAGS_C_FLAGS_DEBUG "-O0" )
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS_DEBUG "-O0" )

set( OVERRIDECOMPILERFLAGS_C_FLAGS_BIT "-O2" )
set( OVERRIDECOMPILERFLAGS_CXX_FLAGS_BIT "-O2" )
1 change: 1 addition & 0 deletions tests/ecbuild_override_compiler_flags/emptyfile.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
! An empty file
1 change: 1 addition & 0 deletions tests/ecbuild_override_compiler_flags/emptyfile.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// An empty file
1 change: 1 addition & 0 deletions tests/ecbuild_override_compiler_flags/emptyfile.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// An empty file
22 changes: 22 additions & 0 deletions tests/ecbuild_override_compiler_flags/run-test.sh.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash

set -e

HERE="$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd -P )"

cd $HERE

rm -rf build # cleanup
mkdir build
cd build

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 ..

cd ..

rm -rf build # cleanup
mkdir build
cd build

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 ..

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
cmake_minimum_required( VERSION 3.12 FATAL_ERROR )

find_package( ecbuild 3.6 REQUIRED )

project(OverrideCompilerFlags VERSION 1.0 LANGUAGES C CXX Fortran)

ecbuild_override_compiler_flags( COMPILE_FLAGS compiler_flags.cmake )

ecbuild_add_library(
TARGET overrideflags
SOURCES emptyfile.c emptyfile.cxx emptyfile.F90
)

get_property( _flags SOURCE emptyfile.c PROPERTY COMPILE_FLAGS )
if( CMAKE_BUILD_TYPE MATCHES BIT )
if( NOT ${_flags} MATCHES "-g -fPIC -O2" )
message(${_flags})
message(FATAL_ERROR "Incorrect BIT flags for emptyfile.c")
endif()
elseif( CMAKE_BUILD_TYPE MATCHES DEBUG )
if( NOT ${_flags} MATCHES "-g -fPIC -O0" )
message(${_flags})
message(FATAL_ERROR "Incorrect DEBUG flags for emptyfile.c")
endif()
endif()

get_property( _flags SOURCE emptyfile.cxx PROPERTY COMPILE_FLAGS )
if( CMAKE_BUILD_TYPE MATCHES BIT )
if( NOT ${_flags} MATCHES "-g -fPIC -O2" )
message(${_flags})
message(FATAL_ERROR "Incorrect BIT flags for emptyfile.cxx")
endif()
elseif( CMAKE_BUILD_TYPE MATCHES DEBUG )
if( NOT ${_flags} MATCHES "-g -fPIC -O0" )
message(${_flags})
message(FATAL_ERROR "Incorrect DEBUG flags for emptyfile.cxx")
endif()
endif()

get_property( _flags SOURCE emptyfile.F90 PROPERTY COMPILE_FLAGS )
if( NOT ${_flags} MATCHES "-g -fortran_only_flag" )
message(${_flags})
message(FATAL_ERROR "Incorrect flags for emptyfile.F90")
endif()

0 comments on commit c4acdc0

Please sign in to comment.