Background
I'm working on updating the build system for legacy C/C++ code from the early 90s, the original build system is based on cfront. The code has ~1000 global variables that are scattered all over the ~100 source files (code base ~200k lines).
The CMake based build system that I currently have can build on Linux with GCC, MacOS with Clang, and Windows with MinGW. However, I get linker errors for MSVC on Windows because of the global variables. It turns out that for some reason MSVC also mangles the names of global variables.
Question
It seems that prepending every global variable with extern "C"
would work. However, that would be very labor intensive. (Unless someone knows of an IDE or static analyzer that could do the job.) Hence my question, is it possible to somehow force MSVC to not mangle the global variables using some sort of option or file?
Minimal working example
CMakeLists.txt
project(test)
set(SOURCES foo.c)
set(BINNAME main)
foreach(f ${SOURCES})
set_source_files_properties(${f} PROPERTIES LANGUAGE CXX)
endforeach()
add_executable(${BINNAME}
main.c
${SOURCES})
main.c
#include <stdio.h>
extern void foo();
extern int sv;
int main() {
if(sv)
foo();
return 0;
}
foo.c
#include "foo.h"
int sv = 10;
void foo() {
printf("\nThe value of global variable sv is:%d\n", sv);
}
foo.h
#include <stdio.h>
extern "C" {
void foo();
}
More info
- Running the above example on Windows with MSVC will give you the following output:
CustomBuild:
Building Custom Rule C:/Users/matya/sandbox/git/cmake/CMakeLists.txt
ClCompile:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\HostX64\x64\CL.e
xe /c /nologo /W3 /WX- /diagnostics:column /O2 /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Releas
e\"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /Fo"main.dir\Release\\"
/Fd"main.dir\Release\vc142.pdb" /Gd /TC /errorReport:queue C:\Users\matya\sandbox\git\cmake\main.c
main.c
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\HostX64\x64\CL.e
xe /c /nologo /W3 /WX- /diagnostics:column /O2 /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Releas
e\"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /Fo"main.dir\Release\\"
/Fd"main.dir\Release\vc142.pdb" /Gd /TP /errorReport:queue C:\Users\matya\sandbox\git\cmake\foo.c
foo.c
Link:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\HostX64\x64\link
.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\matya\sandbox\git\cmake\build\Release\main.exe" /INCREMENTAL:NO /NOLO
GO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib a
dvapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"C:/Users/matya
/sandbox/git/cmake/build/Release/main.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/Us
ers/matya/sandbox/git/cmake/build/Release/main.lib" /MACHINE:X64 /machine:x64 main.dir\Release\main.obj
main.dir\Release\foo.obj
main.obj : error LNK2019: unresolved external symbol sv referenced in function main [C:\Users\matya\sandbox\gi
t\cmake\build\main.vcxproj]
Hint on symbols that are defined and could potentially match:
"int sv" (?sv@@3HA)
C:\Users\matya\sandbox\git\cmake\build\Release\main.exe : fatal error LNK1120: 1 unresolved externals [C:\User
s\matya\sandbox\git\cmake\build\main.vcxproj]
Done Building Project "C:\Users\matya\sandbox\git\cmake\build\main.vcxproj" (default targets) -- FAILED.
Done Building Project "C:\Users\matya\sandbox\git\cmake\build\ALL_BUILD.vcxproj" (default targets) -- FAILED.
Build FAILED.
"C:\Users\matya\sandbox\git\cmake\build\ALL_BUILD.vcxproj" (default target) (1) ->
"C:\Users\matya\sandbox\git\cmake\build\main.vcxproj" (default target) (3) ->
(Link target) ->
main.obj : error LNK2019: unresolved external symbol sv referenced in function main [C:\Users\matya\sandbox\
git\cmake\build\main.vcxproj]
C:\Users\matya\sandbox\git\cmake\build\Release\main.exe : fatal error LNK1120: 1 unresolved externals [C:\Us
ers\matya\sandbox\git\cmake\build\main.vcxproj]
As I mentioned earlier the above runs fine on Windows with MinGW (and also Linux GCC, etc.)
In the above example, if I simply prepend
int sv = 10
infoo.c
withextern "C"
, it also compiles with MSVC.I use the following commands to run
cmake
:
mkdir build
cd build
cmake ..
cmake --build . --config Release -v
Thanks!