3

I just discovered a copy and paste error in my CMake code:

function(name)
   # do something ...
endfunction()

function(name)
   # do something else ...
endfunction()

I had copied, renamed and changed the function several times. Apparently I created one copy too many, so that the original function now existed twice. Later I changed one of the two. The error was discovered because the original version was defined after the changed function and therefore my changes had no effect.

Is there a way to detect a double defined function?

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51

1 Answers1

3

It seems that CMake itself has no switch which prevents double function definition. You could run cmake in a trace mode:

cmake --trace-format=json-v1 --trace-redirect=trace.json <... other params>

The resulted trace.json file in JSON format will accumulate (amond other info) all calls to 'function' command:

...
{"args":["my_func"],"cmd":"function","file":"/home/tester/tests/cmake/CMakeLists.txt","frame":1,"line":4,"time":1684839183.3986549}
{"args":["my_func"],"cmd":"function","file":"/home/tester/tests/cmake/CMakeLists.txt","frame":1,"line":8,"time":1684839183.398663}
...

Then you may write a script which reads resulted JSON file and finds calls to 'function' command with the same names.

E.g. following jq script:

# Select only functions definitions
map(select(.cmd=="function")) |
# Simplify information to only a function name and its location.
map({"func": .args[0], "file": (.file + ":" + (.line|tostring))}) |
# Group by function names
group_by(.func) |
# Select those groups which have more than one entry.
map(select(length>1))

with usage

jq -s -f <path/to/script> trace.json

could produce such output:

[
  [
    {
      "func": "my_func",
      "file": "/home/tester/tests/cmake/CMakeLists.txt:4"
    },
    {
      "func": "my_func",
      "file": "/home/tester/tests/cmake/CMakeLists.txt:8"
    }
  ]
]

Note, that the approach above won't work in case CMake will find a syntax error (like with if(AAA AAA) command) while processing your project: in that case the trace file will be empty.

However, hitting e.g. message(FATAL_ERROR) won't prevent CMake to trace all commands before the failure.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153