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()
|