5

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
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • 1
    According to [documentation](https://cmake.org/cmake/help/v3.0/module/CheckTypeSize.html), macro `check_type_size()` supports *LANGUAGE* option. Bad news is that `test_big_endian()` doesn't support such option even in newest versions, and pre 3.0 CMake doesn't support this option even for `check_type_size`. But these are just cmake modules. You may take code from the them, and adjust it for your needs. – Tsyvarev Jun 20 '16 at 21:27
  • Does this answer your question? [Can CMake use g++ to compile C files?](https://stackoverflow.com/questions/7690800/can-cmake-use-g-to-compile-c-files) – user7610 Feb 18 '22 at 11:16

3 Answers3

4

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

Florian
  • 39,996
  • 9
  • 133
  • 149
  • Thanks Florian. One of our mandates is to *not* require users to upgrade. In some settings, its a Change Control nightmare, requiring an executive to sign-off on it. (I've worked in those environments, like certain branches of US government). Its easier on everyone if our stuff "just works". – jww Jun 22 '16 at 20:56
  • @jww Ok, I can certainly understand your reasoning. I was just hoping for an easier solution. I've updated my answer accordingly. Does the above solution work for you? Otherwise I can also add the `try_compile()` code (bypassing the need to use the `CheckTypeSize` module). – Florian Jun 23 '16 at 07:31
0

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.

user7610
  • 25,267
  • 15
  • 124
  • 150
0

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.

Russ Schultz
  • 2,545
  • 20
  • 22