能否仅用宏包裹函数调用?需通过CMake配置且不可修改源码
Got it, let's tackle this problem. You want to replace all calls to foo() with bar() using a macro, but you're hitting redefinition errors because the macro also replaces the foo function definition. Linker wrapping isn't an option, and you can't modify the source code—all changes need to happen via CMake. Here's how to fix this:
The Core Idea
The key is to apply the macro only to source files that call foo, not to the file that defines foo. This way, the original foo definition stays intact, while all calls get replaced with bar.
Step-by-Step Implementation
1. Identify the Source File with foo's Definition
First, figure out which file contains the original int foo(int x) { ... } definition (let's say it's foo.c for this example).
2. Configure CMake to Apply the Macro Selectively
Add these lines to your CMakeLists.txt:
# Replace this with your actual target name add_executable(your_target main.c foo.c bar.c) # Apply the macro to all files: replace "foo" with "bar" target_compile_definitions(your_target PRIVATE foo=bar) # Exclude the foo definition file from the macro—keep "foo" as-is here set_source_files_properties(foo.c PROPERTIES COMPILE_DEFINITIONS "")
How It Works
- When compiling files like
main.c, thefoo=barmacro will turnint a = foo(2);intoint a = bar(2);. - When compiling
foo.c, we clear the compile definitions, so the originalint foo(int x) { ... }remains unchanged. - You just need to ensure
baris properly defined (either in another source file likebar.cor a header included everywhere).
What If You Don't Know Where foo Is Defined?
If you can't pinpoint the definition file, there's a trick using preprocessor conditionals (though it's a bit hacky):
First, generate a small header file via CMake (so you don't modify existing source code):
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/wrap_foo.h.in ${CMAKE_CURRENT_BINARY_DIR}/wrap_foo.h @ONLY )
Create wrap_foo.h.in with this content:
#ifndef WRAP_FOO_SKIP #define foo bar #endif
Then adjust your CMake configuration to include this header and skip the macro for the definition file:
target_include_directories(your_target PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_compile_definitions(your_target PRIVATE -include wrap_foo.h) # Define WRAP_FOO_SKIP for the file that contains foo's definition set_source_files_properties(foo.c PROPERTIES COMPILE_DEFINITIONS "WRAP_FOO_SKIP")
This way, in foo.c, the foo=bar macro gets skipped because WRAP_FOO_SKIP is defined, preserving the original function definition.
Why This Works Better Than Linker Wrapping
Since you can't use linker wrapping (like --wrap in GCC), this preprocessor-based approach with CMake file control gives you exact control over which files get the macro replacement, avoiding redefinition errors entirely—no source code edits needed.
内容的提问来源于stack exchange,提问作者mmichal10

