1# check whether the user wants to overload compile flags upon calling make
2#
3# Provides the following macros:
4#
5#   initialize_compiler_script() : needs to be called before further flags are added to CMAKE_CXX_FLAGS
6#   finalize_compiler_script()   : needs to be called at the end of the cmake macros, e.g. in finalize_dune_project
7#
8# Those two macro calls are hooked into dune_project/finalize_dune_project.
9#
10# .. cmake_variable:: ALLOW_CXXFLAGS_OVERWRITE
11#
12#    Setting this option will allow you to overload preprocessor definitions from
13#    the command line, as it was possible naturally with the autotools build system.
14#    This feature only works with a :code:`Unix Makefiles` based generator. You can
15#    use it as:
16#
17#    :code:`make CXXFLAGS="your flags" GRIDTYPE="grid type"`
18#
19#    :code:`GRIDTYPE` can be anything defined in :code:`config.h` via the :ref:`dune_define_gridtype` macro from dune-grid.
20#    Furthermore any CPP variable of the form :code:`-DVAR=VALUE` can be overloaded on the command line.
21#
22#    .. note::
23#       If you don't know what this is or what it's good for, don't use it.
24#
25include_guard(GLOBAL)
26
27option(ALLOW_CXXFLAGS_OVERWRITE OFF)
28option(ALLOW_CFLAGS_OVERWRITE OFF)
29
30set(CXX_COMPILER_SCRIPT "${CMAKE_BINARY_DIR}/CXX_compiler.sh" )
31set(C_COMPILER_SCRIPT "${CMAKE_BINARY_DIR}/C_compiler.sh" )
32
33macro(find_extended_unix_commands)
34  include(FindUnixCommands)
35  set(FLAGSNAMES "ALLOW_CXXFLAGS_OVERWRITE and/or ALLOW_CFLAGS_OVERWRITE")
36  find_program (GREP_PROGRAM grep)
37  if(NOT GREP_PROGRAM)
38    message( SEND_ERROR "grep not found, please disable ${FLAGSNAMES}")
39  endif()
40  find_program (SED_PROGRAM  sed)
41  if(NOT SED_PROGRAM)
42    message( SEND_ERROR "sed not found, please disable ${FLAGSNAMES}")
43  endif()
44  find_program (CUT_PROGRAM  cut)
45  if(NOT CUT_PROGRAM)
46    message( SEND_ERROR "cut not found, please disable ${FLAGSNAMES}")
47  endif()
48  find_program (ENV_PROGRAM  env)
49  if(NOT ENV_PROGRAM)
50    message( SEND_ERROR "env not found, please disable ${FLAGSNAMES}")
51  endif()
52  find_program (ECHO_PROGRAM echo)
53  if(NOT ECHO_PROGRAM)
54    message( SEND_ERROR "echo not found, please disable ${FLAGSNAMES}")
55  endif()
56  find_program (CHMOD_PROGRAM chmod)
57  if(NOT CHMOD_PROGRAM)
58    message( SEND_ERROR "chmod not found, please disable ${FLAGSNAMES}")
59  endif()
60  mark_as_advanced(GREP_PROGRAM)
61  mark_as_advanced(SED_PROGRAM)
62  mark_as_advanced(CUT_PROGRAM)
63  mark_as_advanced(ENV_PROGRAM)
64  mark_as_advanced(ECHO_PROGRAM)
65  mark_as_advanced(CHMOD_PROGRAM)
66endmacro(find_extended_unix_commands)
67
68# init compiler script and store CXX flags
69macro(initialize_compiler_script)
70  if(ALLOW_CXXFLAGS_OVERWRITE AND (${CMAKE_GENERATOR} MATCHES ".*Unix Makefiles.*"))
71    # check for unix commands necessary
72    find_extended_unix_commands()
73    # set CXXFLAGS as environment variable
74    set( DEFAULT_CXXFLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "default CXX flags")
75    set( CMAKE_CXX_FLAGS "" )
76    set( DEFAULT_CXX_COMPILER ${CMAKE_CXX_COMPILER} )
77    set( CXX_COMPILER_SCRIPT_FILE "#!${BASH}\nexec ${CMAKE_CXX_COMPILER} \"\$@\"")
78    file(WRITE ${CXX_COMPILER_SCRIPT} "${CXX_COMPILER_SCRIPT_FILE}")
79    execute_process(COMMAND ${CHMOD_PROGRAM} 755 ${CXX_COMPILER_SCRIPT})
80    set(CMAKE_CXX_COMPILER ${CXX_COMPILER_SCRIPT})
81  endif()
82  if(ALLOW_CFLAGS_OVERWRITE AND (${CMAKE_GENERATOR} MATCHES ".*Unix Makefiles.*"))
83    # check for unix commands necessary
84    find_extended_unix_commands()
85    # set CFLAGS as environment variable
86    set( DEFAULT_CFLAGS ${CMAKE_C_FLAGS} CACHE STRING "default C flags")
87    set( CMAKE_C_FLAGS "" )
88    set( DEFAULT_C_COMPILER ${CMAKE_C_COMPILER} )
89    set( C_COMPILER_SCRIPT_FILE "#!${BASH}\nexec ${CMAKE_C_COMPILER} \"\$@\"")
90    file(WRITE ${C_COMPILER_SCRIPT} "${C_COMPILER_SCRIPT_FILE}")
91    execute_process(COMMAND ${CHMOD_PROGRAM} 755 ${C_COMPILER_SCRIPT})
92    set(CMAKE_C_COMPILER ${C_COMPILER_SCRIPT})
93  endif()
94endmacro()
95
96# finalize compiler script and write it
97macro(finalize_compiler_script)
98  if(${CMAKE_GENERATOR} MATCHES ".*Unix Makefiles.*")
99    # check CXX compiler
100    if((ALLOW_CXXFLAGS_OVERWRITE))
101      set(COMPILERS "CXX")
102    endif()
103    # check C compiler
104    if((ALLOW_CFLAGS_OVERWRITE))
105      set(COMPILERS ${COMPILERS} "C")
106    endif()
107
108    # for the found compilers for flag overloading generate compiler script
109    foreach(COMP ${COMPILERS})
110      set( COMPILER_SCRIPT_FILE "#!${BASH}\nSED=${SED_PROGRAM}\nGREP=${GREP_PROGRAM}")
111      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nCUT=${CUT_PROGRAM}\nENV=${ENV_PROGRAM}\nECHO=${ECHO_PROGRAM}")
112      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n# store flags\nFLAGS=\"\$@\"")
113      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nMAKE_EXECUTABLE_NEW=0\n")
114      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nif [ \"\$${COMP}FLAGS\" == \"\" ]; then\n  # default ${COMP} flags\n  ${COMP}FLAGS=\"${DEFAULT_CXXFLAGS}\"\nfi\n")
115      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nif [ \"\$EXTRA_${COMP}FLAGS\" != \"\" ]; then\n  # extra ${COMP} flags\n  ${COMP}FLAGS=\"$${COMP}FLAGS $EXTRA_${COMP}FLAGS\"\nfi\n")
116      # only for CXX we need to scan config.h for GRIDTYPE
117      if( ${COMP} STREQUAL "CXX" )
118        set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nGRIDS=\nCONFIG_H=${CMAKE_BINARY_DIR}/config.h")
119        set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nif [ \"\$GRIDTYPE\" != \"\" ]; then")
120        set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  GRIDS=`\$GREP \"defined USED_[A-Z_]*_GRIDTYPE\" \$CONFIG_H | \$SED 's/\\(.*defined USED\\_\\)\\(.*\\)\\(\\_GRIDTYPE*\\)/\\2/g'`\nfi\n")
121      endif()
122      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nOLDFLAGS=\$FLAGS\nFLAGS=")
123      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nfor FLAG in \$OLDFLAGS; do")
124      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  NEWFLAG=\$FLAG\n  VARNAME=`\$ECHO \$FLAG | \$GREP \"\\-D\" | \$SED 's/-D//g'`")
125      # only for CXX we have GRIDTYPE
126      if( ${COMP} STREQUAL "CXX" )
127        set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  for GRID in \$GRIDS; do\n    if [ \"\$VARNAME\" == \"\$GRID\" ]; then\n      NEWFLAG=\"-D\$GRIDTYPE\"\n      break\n    fi\n  done")
128      endif()
129      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  VARNAME=`\$ECHO \$VARNAME | \$GREP \"=\" | \$CUT -d \"=\" -f 1`")
130      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  if [ \"\$VARNAME\" != \"\" ]; then\n    VAR=`\$ENV | \$GREP \$VARNAME`\n    if [ \"\$VAR\" != \"\" ]; then")
131      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n      # add variable from environment to flags list\n      NEWFLAG=\"-D\$VARNAME=\${!VARNAME}\"\n    fi\n  fi")
132      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n  FLAGS=\"\$FLAGS \$NEWFLAG\"\ndone")
133      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\n\$ECHO \"${DEFAULT_${COMP}_COMPILER} \$${COMP}FLAGS \$FLAGS\"")
134      set( COMPILER_SCRIPT_FILE "${COMPILER_SCRIPT_FILE}\nexec ${DEFAULT_${COMP}_COMPILER} \$${COMP}FLAGS \$FLAGS")
135      message("-- Generating ${COMP} compiler script for ${COMP}FLAGS overloading on command line")
136      if( ${COMP} STREQUAL "CXX" )
137        file(WRITE ${CXX_COMPILER_SCRIPT} "${COMPILER_SCRIPT_FILE}")
138      else()
139        file(WRITE ${C_COMPILER_SCRIPT} "${COMPILER_SCRIPT_FILE}")
140      endif()
141    endforeach()
142  endif()
143endmacro()
144