Fix the cmake parser to identify more patterns

This commit is contained in:
Rafael Cardoso Fernandes Sousa 2021-11-24 14:07:28 -06:00
parent ec4daf420f
commit fb891f33da
1 changed files with 149 additions and 47 deletions

View File

@ -15,35 +15,83 @@ endfunction ()
# Reads a Makefile into CMake vars.
macro(ParseMakefileVars MAKEFILE_IN)
message(STATUS "Reading vars from ${MAKEFILE_IN}...")
set (IfElse 0)
set (ElseSeen 0)
set (C_COMPILER ${CMAKE_C_COMPILER_ID})
set (IfElse 0)
set (ElseSeen 0)
set (SkipIfs 0)
set (SkipElse 0)
file(STRINGS ${MAKEFILE_IN} makefile_contents)
foreach (makefile_line ${makefile_contents})
#message(STATUS "parsing ${makefile_line}")
if (${IfElse} GREATER 0)
#message(STATUS "parsing ${makefile_line}")
# Skip the entire scope of the else statement given that the if statement that precedes it has the valid condition.
# The variable SkipIfs is used to identify which endif statement closes the scope of the else statement.
if (${SkipElse} EQUAL 1)
#message(STATUS "skipping ${makefile_line}")
string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
MATH(EXPR SkipIfs "${SkipIfs}+1")
endif ()
string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
# message(STATUS "ENDIF ${makefile_line}")
set (IfElse 0)
set (ElseSeen 0)
if (${SkipIfs} EQUAL 0)
set (SkipElse 0)
else ()
MATH(EXPR SkipIfs "${SkipIfs}-1")
endif ()
endif ()
continue ()
endif ()
# The variable IfElse is greater than 0 if and only if the previously parsed line is an if statement.
if (${IfElse} GREATER 0)
# If the current scope is the one that has to be skipped, the if/endif/else statements
# along with it till the endif that closes the current scope have to be ignored as well.
string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1))
#message(STATUS "skipping ${makefile_line}")
MATH(EXPR SkipIfs "${SkipIfs}+1")
continue ()
endif ()
endif ()
string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
if (${SkipIfs} EQUAL 0)
#message(STATUS "ENDIF ${makefile_line}")
set (IfElse 0)
set (ElseSeen 0)
else ()
#message(STATUS "skipping ${makefile_line}")
MATH(EXPR SkipIfs "${SkipIfs}-1")
endif ()
continue ()
endif ()
string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
# message(STATUS "ELSE ${makefile_line}")
set (ElseSeen 1)
continue ()
endif()
if ( (${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR ( ${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1))
# message(STATUS "skipping ${makefile_line}")
continue ()
if (NOT "${line_match}" STREQUAL "")
if (${SkipIfs} EQUAL 0)
#message(STATUS "ELSE ${makefile_line}")
set (ElseSeen 1)
else ()
#message(STATUS "skipping ${makefile_line}")
endif ()
continue ()
endif()
# Skip the lines that are not part of the path that has to be taken.
if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1) OR (${SkipIfs} GREATER 0))
#message(STATUS "skipping ${makefile_line}")
continue ()
endif ()
endif ()
# Skip commented lines (the ones that start with '#')
string(REGEX MATCH "[ \t]*\\#.*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "skipping ${makefile_line}")
continue ()
endif ()
string(REGEX MATCH "([0-9_a-zA-Z]+)[ \t]*=[ \t]*(.+)$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "match on ${line_match}")
#message(STATUS "match on ${line_match}")
set(var_name ${CMAKE_MATCH_1})
# set(var_value ${CMAKE_MATCH_2})
#set(var_value ${CMAKE_MATCH_2})
string(STRIP ${CMAKE_MATCH_2} var_value)
# check for Makefile variables in the string, e.g. $(TSUFFIX)
string(REGEX MATCHALL "\\$\\(([0-9_a-zA-Z]+)\\)" make_var_matches ${var_value})
@ -54,39 +102,93 @@ macro(ParseMakefileVars MAKEFILE_IN)
string(REPLACE "$(${make_var})" "${${make_var}}" var_value ${var_value})
endforeach ()
set(${var_name} ${var_value})
else ()
string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "match on include ${line_match}")
ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1})
else ()
# message(STATUS "unmatched line ${line_match}")
string(REGEX MATCH "ifeq \\(\\$\\(([_A-Z]+)\\),[ \t]*([0-9_A-Z]+)\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
# message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_2}")
if (DEFINED ${${CMAKE_MATCH_1}} AND ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2})
# message (STATUS "condition is true")
set (IfElse 1)
else ()
set (IfElse 2)
endif ()
continue ()
endif ()
# Include a new file to be parsed
string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "match on include ${line_match}")
ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1})
continue ()
endif ()
# The if statement that precedes this else has the path taken
# Thus, this else statement has to be skipped.
string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "skipping ${makefile_line}")
set (SkipElse 1)
continue()
endif()
# Example 1: ifdef HAVE_MSA
# Example 2: ifndef ZNRM2KERNEL
string(REGEX MATCH "(ifdef|ifndef) ([0-9_A-Z]+)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "${CMAKE_MATCH_1} first: ${CMAKE_MATCH_2}")
set (ElseSeen 0)
if (DEFINED ${CMAKE_MATCH_2})
if (${CMAKE_MATCH_1} STREQUAL "ifdef")
#message (STATUS "condition is true")
set (IfElse 1)
else ()
string(REGEX MATCH "ifneq \\(\\$\\(([_A-Z]+)\\),[ \t]*([0-9_A-Z]+)\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
# message(STATUS "IFNEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_2}")
if ( ${CMAKE_MATCH_1} STREQUAL C_COMPILER)
set (CMAKE_MATCH_1 CMAKE_C_COMPILER)
endif ()
if (NOT ( ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2}))
# message (STATUS "condition is true")
set (IfElse 1)
else ()
set (IfElse 2)
endif ()
endif ()
set (IfElse 2)
endif ()
else ()
if (${CMAKE_MATCH_1} STREQUAL "ifdef")
set (IfElse 2)
else ()
#message (STATUS "condition is true")
set (IfElse 1)
endif ()
endif ()
continue ()
endif ()
# Example 1: ifeq ($(SGEMM_UNROLL_M), 16)
# Example 2: ifeq ($(SGEMM_UNROLL_M)x$(SGEMM_UNROLL_N), 8x8)
# Example 3: ifeq ($(__BYTE_ORDER__)$(ELF_VERSION),__ORDER_BIG_ENDIAN__2)
# Ignore the second group since (?:...) does not work on cmake
string(REGEX MATCH "ifeq \\(\\$\\(([0-9_A-Z]+)\\)(([0-9_A-Za-z]*)\\$\\(([0-9_A-Z]+)\\))?,[ \t]*([0-9_A-Za-z]+)\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4} fourth: ${CMAKE_MATCH_5}")
if (DEFINED ${CMAKE_MATCH_1})
if (DEFINED ${CMAKE_MATCH_4})
set (STR ${${CMAKE_MATCH_1}}${CMAKE_MATCH_3}${${CMAKE_MATCH_4}})
else ()
set (STR ${${CMAKE_MATCH_1}})
endif ()
if (${STR} STREQUAL ${CMAKE_MATCH_5})
#message (STATUS "condition is true")
set (IfElse 1)
continue ()
endif ()
endif ()
set (IfElse 2)
continue ()
endif ()
# Example 1 (Group 3): ifneq ($(SGEMM_UNROLL_M), $(SGEMM_UNROLL_N))
# Example 2 (Group 4): ifneq ($(C_COMPILER), PGI)
string(REGEX MATCH "ifneq \\(\\$\\(([0-9_A-Z]+)\\),[ \t]*(\\$\\(([0-9_A-Z]+)\\)|([0-9_A-Z]+))\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "IFNEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4}")
set (ElseSeen 0)
set (HasValidGroup 0)
if (DEFINED ${CMAKE_MATCH_3})
set (HasValidGroup 1)
set (STR ${${CMAKE_MATCH_3}})
elseif (NOT ${CMAKE_MATCH_4} STREQUAL "")
set (HasValidGroup 1)
set (STR ${CMAKE_MATCH_4})
endif ()
if (DEFINED ${CMAKE_MATCH_1} AND ${HasValidGroup} EQUAL 1)
if (NOT (${${CMAKE_MATCH_1}} STREQUAL ${STR}))
#message (STATUS "condition is true")
set (IfElse 1)
continue ()
endif ()
endif ()
set (IfElse 2)
continue ()
endif ()
#message(STATUS "unmatched line ${line_match}")
endforeach ()
endmacro ()