jww
jww

Reputation: 102245

Tell CMake to use C++ compiler for C files coming from CMake?

This is similar to Force CMake to use C++ compiler for C files with Visual Studio, but its not quite the same. Its not the same because a its CMake file causing the failure; and I'm working on nearly every modern platform, from BSDs and OS X through Solaris and Unix.

I tried to avoid useless checks being performed by CMake:

project(cryptopp, CXX)

Here's what happens when I attempt to generate the makefile:

$ cmake .
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
CMake Error at /usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:82 (try_compile):
  Unknown extension ".c" for file

    /home/jeffrey/cryptopp/CMakeFiles/CheckTypeSize/CMAKE_SIZEOF_UNSIGNED_SHORT.c

  try_compile() works only for enabled languages.  Currently these are:

    CXX

  See project() command to enable other languages.
Call Stack (most recent call first):
  /usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:167 (__check_type_size_impl)
  /usr/share/cmake-2.8/Modules/TestBigEndian.cmake:27 (CHECK_TYPE_SIZE)
  CMakeLists.txt:49 (TEST_BIG_ENDIAN)

We don't have any C files in our project, so we should be safe with project(cryptopp, CXX) (if I am reading cmake --help-command project correctly).

The cited question talks about project files, but not CMake files.

How do I tell CMake to use C++ compiler for all files, including its own CMake files?


I'm on Ubuntu 12 LTS, and it provides:

$ cmake --version
cmake version 2.8.7

Upvotes: 6

Views: 7662

Answers (3)

Russ Schultz
Russ Schultz

Reputation: 2689

Another braindead way of doing this (I just tried the set_source_files_properties() route and it just didn't even try to compile the files).

Rather than figure out the rats nest of cmake stuff I'm saddled with, I just added a C++ file that #includes the .c file, and added the C++ file to the CMakeLists.txt sources.

Braindead and stupid, but I'm having to deal with horrific code I'm importing. C header files without extern "C" in them, being used by C++ files.

Upvotes: 0

user7610
user7610

Reputation: 28811

set_source_files_properties

The CMake setting of (my) choice here would be the set_source_files_properties command. https://cmake.org/cmake/help/latest/command/set_source_files_properties.html

set(qpid_dispatch_SOURCES
  alloc.c
  alloc_pool.c
  aprintf.c
  amqp.c
  atomic.c
# [...]
)
set_source_files_properties(${qpid_dispatch_SOURCES} PROPERTIES LANGUAGE CXX)
add_library(qpid-dispatch OBJECT ${qpid_dispatch_SOURCES})

As described in the linked docs, CMake 3.18 changed the scoped effect of set_source_files_properties. See the DIRECTORY and TARGET_DIRECTORY options. Therefore, to apply source file property recursively to all files in your project, your CMakeLists.txt should look something like this

cmake_minimum_required(VERSION 3.20)
project(qpid-dispatch LANGUAGES C CXX)

# [...]

add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(router)

# [...]

file(GLOB_RECURSE CFILES "*.c")
set_source_files_properties(${CFILES}
        DIRECTORY src tests router
        PROPERTIES LANGUAGE CXX)

Copy the world

There is another approach that I've heard can be made to work: in your CMakeLists.txt, recursively copy all *.c files into *.cpp files and declare separate CMake targets to compile the copies. This has the advantage of allowing you to produce C-compiled and CXX-compiled artifacts at the same time, should you need anything like that.

Upvotes: 1

Florian
Florian

Reputation: 42862

There are ways to add .c as a valid file extension for the CXX compiler. Even this being very advanced CMake stuff, you may need - if you are bound to support older versions of CMake - a "make rules overwrite script" anyway.

So I've successfully tested the following:

CryptoppMakeRulesOverwrite.cmake

list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)

set(CMAKE_USER_MAKE_RULES_OVERRIDE "CryptoppMakeRulesOverwrite.cmake")

project(cryptopp CXX)

include(CheckTypeSize)
CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT)

As @Tsyvarev has commented check_type_size() supports a LANGUAGE parameter, but unfortunately not for CMake version 2.8.7. But this older version does already support CMAKE_USER_MAKE_RULES_OVERRIDE.

So I'm still wondering if not the best solution would be to go to a newer version of CMake (forcing some users of older CMake versions to upgrade). Or writing your own try_compile() snippets.

References

Upvotes: 4

Related Questions