How to change the entry point of an application using Visual Studio and Clang Link to heading

I’m writing this just just in case this problem happens to somebody else because it isn’t documented anywhere. So, simply changing the /entry option for a Visual Studio project built with Clang causes a myriad of linking errors due to the runtime libraries that are linked by default when using the MSVC compiler. In order to fix the problems that happen you need to do this:

  • Change the entry point in Project Properties -> Linker -> Advanced -> Entry Point (to entry in this example).
  • Add the following libraries in Project Properties -> Linker -> Input -> Additional Dependencies: ucrt.lib;libvcruntime.lib;vcruntime.lib;msvcrt.lib;.
  • Add the following directives in Project Properties -> Linker -> Command line:
/alternatename:__acrt_initialize=__scrt_stub_for_acrt_initialize /alternatename:__acrt_uninitialize=__scrt_stub_for_acrt_uninitialize /alternatename:__acrt_uninitialize_critical=__scrt_stub_for_acrt_uninitialize_critical /alternatename:__acrt_thread_attach=__scrt_stub_for_acrt_thread_attach /alternatename:__acrt_thread_detach=__scrt_stub_for_acrt_thread_detach /alternatename:_is_c_termination_complete=__scrt_stub_for_is_c_termination_complete /alternatename:__vcrt_initialize=__scrt_stub_for_acrt_initialize /alternatename:__vcrt_uninitialize=__scrt_stub_for_acrt_uninitialize /alternatename:__vcrt_uninitialize_critical=__scrt_stub_for_acrt_uninitialize_critical /alternatename:__vcrt_thread_attach=__scrt_stub_for_acrt_thread_attach /alternatename:__vcrt_thread_detach=__scrt_stub_for_acrt_thread_detach 

The directives are optional, because you can just as well write your own wrappers for the alternate names. The original ones from Microsoft are the following:

//
// ucrt_stubs.cpp
//
//      Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source file defines stub alternatives for several functions that are
// only present in the static Universal CRT (not in the Universal CRT DLLs).
//
#include <vcruntime.h>

extern "C" int __scrt_ucrt_dll_is_in_use = 1;

extern "C" bool __cdecl __scrt_stub_for_acrt_initialize()
{
    return true;
}

extern "C" bool __cdecl __scrt_stub_for_acrt_uninitialize(bool)
{
    return true;
}

extern "C" bool __cdecl __scrt_stub_for_acrt_uninitialize_critical(bool)
{
    return true;
}

extern "C" bool __cdecl __scrt_stub_for_acrt_thread_attach()
{
    return true;
}

extern "C" bool __cdecl __scrt_stub_for_acrt_thread_detach()
{
    return true;
}

extern "C" int __cdecl __scrt_stub_for_is_c_termination_complete()
{
    return 0;
}

After that, add the following code to some source file:

#include <Windows.h>
#include <stdio.h>

#ifdef _CONSOLE
extern "C" int mainCRTStartup();
#define CRTStartup mainCRTStartup
#else
extern "C" int WinMainCRTStartup();
#define CRTStartup WinMainCRTStartup
#endif

int entry(void)
{
  printf("%s: At entry point\n", __FUNCTION__);
  return CRTStartup();
}

And, voilà! Your application will now start at entry, where you can do whatever you like and then run CRTStartup to continue with the original program.