ysflight.com


2014/12/20 Mixing C++11 files and Objective-C files in the same CMake project.

I was able to make CMake build environment for most of my projects (for hobby and real-work).  In doing this, only one problem (so far) that I could not find a direct solution with Google was the way to mix C++ source files that uses C++11 features and Objective-C source files.

Objective-C is an inferior copy of the C language.  It threw away the beauty of simplicity and failed to add object-oriented programming concept.  Due to the fragile language foundation, it required ad-hoc language-specification changes, which made older code unusable at least twice in the language history.  Objective-C is a bad programming language.  It is the best if you don't have to use it.

However, Mac OSX programs unfortunately require Objective-C.  Luckily an independent  function in Objective-C can be called from C program, and vise-versa.  C++ can call such functions by using extern "C".  Therefore, you can write a practically functional program by minimizing Objective-C part, and let C++ do the job.

 

To minimize Objective-C code, what you can do is writing a library that entirely isolate Objective-C code inside.  Such a library, for example a library that opens a window and takes keyboard and mouse input, needs to mix C++ sources and Objective-C sources in one project.

The problem arises when you want to use C++11 features in C++ source files of such libraries.  To use C++11 features with GCC or Clang compilers, you need to add a compiler option -std=c++0x.  You can do so by writing inside CMakeLists.txt as:

set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++0x)

However, it turned out CMake has a major bug.  This CMAKE_CXX_FLAGS is also applied to Objective-C sources.  Since there is no standard called c++0x in Objective-C, the compiler takes it as an error.

As I described above, Objective-C is an inferior copy of C.  It is closer to C, far away from C++.  CMAKE_C_FLAGS should be used for Objective-C rather than CMAKE_CXX_FLAGS.

Solution to this problem was difficult.  For other problems I faced, google gave me an answer almost right away.  But, I could not find a solution to this particular problem for this problem for several hours.

The solution that I found finally is to set per-source compiler flags.  For example, if the source files are organized in variable SRCS like:

 set(SRCS
    library_source.cpp
    objectivec_part.m
)

and if the flags that needs to be used only for C++ sources, and never be used for Objective-C sources is defined as:

 set(YS_CXX_FLAGS "-std=c++0x")

then you can write a following loop to give this option only to the files ending with .cpp.

if(YS_CXX_FLAGS)
    foreach(SRC ${SRCS})
        if(${SRC} MATCHES .cpp$)
            set_source_files_properties(
                ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} 
                PROPERTIES 
                COMPILE_FLAGS 
                "${YS_CXX_FLAGS}")
        endif()
    endforeach(SRC)
endif()

 

 

 

Comments are welcome.  Send E-Mail to: 

RETURN TO TOP PAGE

This page is link free, but please link to http://www.ysflight.com.  Please use one of following banners.