[CMake] C++ Exceptions, C sources & MSVC80

Nicolas Tisserand nicolas.tisserand at gmail.com
Tue Apr 8 10:30:28 EDT 2008


Hi CMakers,

I have a CMake project where C and C++ sources are compiled and linked
in the same target (a static library).

The default setting of the generated Visual C++ 2005 projects is to
enable C++ exceptions for C++ code and disable it for C code (/EHsc,
see below).

However, I need to change this flag to /EHs for the C sources, but
cannot manage to make it work with MSVC80 the way I successfully did
for the makefile and XCode generators (adding a C-specific flag to the
CMAKE_C_FLAGS variable for a mixed C/C++ target).

A minimal project exhibiting the behavior can be found below.
This has to be configured against CMake 2.4.8 using the Visual Studio generator.

# CMakeLists.txt ===============================================================

project(Exceptions)

IF    (CMAKE_COMPILER_IS_GNUCC)
  SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions")
ELSEIF(MSVC71 OR MSVC80)
  SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /EHc-")
ENDIF (CMAKE_COMPILER_IS_GNUCC)

# The previous flags won't be reflected in the generated VC 8.0 project.
# This is a real pity, because optimized builds of the resulting program will
# crash.

# The crash occurs because the catch clause is optimized away.
# The catch clause is optimized away because the corresponding try
# block contains only one C function call which is considered non-throwing.
# The C function call which is considered non-throwing because cl.exe is invoked
# with /EHsc, which implies that all extern C functions are non-throwing.

# See: http://msdn2.microsoft.com/en-us/library/1deeycx5(VS.80).aspx for the
# /EHs, /EHsc and /EHc- flags.
# And: http://msdn2.microsoft.com/en-us/library/wfa0edys.aspx for the
# implications of using /EHsc on C translation units.
# (see the table at the bottom of the page)

add_executable(exceptions
  exceptions.cpp
  lib.h
  lib.c
)

#===============================================================================


// lib.h =======================================================================

#ifndef LIB_H
#define LIB_H

#ifdef __cplusplus
extern "C"
{
#endif

typedef void (*ErrorHandler) ();

void libFunction (ErrorHandler errorHandler);

#ifdef __cplusplus
};
#endif

#endif

//==============================================================================


// lib.c =======================================================================

#include "lib.h"

void libFunction (ErrorHandler errorHandler)
{
    errorHandler();
}

//==============================================================================

// exceptions.cpp ==============================================================

#include "lib.h"
#include <iostream>

struct Error
{};

static void errorHandler ()
{
    throw Error();
}

int main ()
{
    try
    {
        libFunction(errorHandler);
    }
    catch (Error&)
    {
        std::cout << "Error caught." << std::endl;
    }
}

//==============================================================================


Maybe there is an easier way to obtain the behavior I am seeking, for
instance flagging the C sources as C++ code.
Any ideas on how to achieve that or anything else :-) ?

-- 
Nicolas


More information about the CMake mailing list