[CMake] Enabling C99 in CMake

Michael Hertling mhertling at online.de
Fri Jul 1 02:12:11 EDT 2011


On 06/27/2011 06:34 PM, Todd Gamblin wrote:
> On Jun 24, 2011, at 11:30 PM, Michael Hertling wrote:
> 
>> On 06/23/2011 06:20 PM, Jed Brown wrote:
>>> On Thu, Jun 23, 2011 at 17:50, Michael Hertling <mhertling at online.de> wrote:
>>>
>>>> You need to use a C99 compiler for your project
>>>
>>>
>>> This is already a problem. C99 introduces new keywords (e.g. restrict) and
>>> removes implicit int. It is entirely possible for part of a project to
>>> include C89-conforming legacy code that is not valid C99. The use of C99 or
>>> C89 should be a file- and directory-level property.
>>
>> That's a really good point and could indeed be very well addressed by
>> a possibility for a project to enable language dialects per directory/
>> target/file as Todd has asked for in his initial posting.
> 
> Yep -- After reading all the responses, think my suggestion was insufficient.  Just having a variable for the compiler flags isn't enough.  Also, I really like the dialects approach here.  This has the potential to take care of not only C99, but also C++ *and* Fortran.  The Fortran support in CMake could really use this kind of thing, as it would be very helpful to know if particular Fortran compilers support F90, F77, F08, etc.
> 
>> In order to
>> achieve this in a platform/compiler-independent manner, take a look at
>> the attached dialects.patch file, a diff against the Modules directory
>> of CMake 2.8.4. It is not meant as a production-ready solution, but as
>> as proof of concept, and it's restricted to the GNU C compiler, though
>> it should be easily applicable to the other compilers known by CMake.
> 
> Thanks for making this!
> 
>> First of all, the new Compiler/LanguageDialects.cmake file provides a
>> function __language_dialects() which accepts a language and a paired
>> list of arguments denoting each supported language dialect followed by
>> the flags to enable it. The function sets up the variable CMAKE_<LANG>_
>> DIALECTS_INIT containing the list of dialects, and for each dialect a
>> variable CMAKE_<LANG>_DIALECT_<DIALECT>_INIT containing the respective
>> flags. The Compiler/GNU-C.cmake file is enhanced to - exemplary - call
>>
>>> __language_dialects(C C90 "-std=c90" C89 "-std=c89" C99 "-std=c99" C9X "-std=c9x" C1X "-std=c1x" ANSI "-ansi")
> 
> This looks great.  One question is what to do with things like gnu99.  This is C99 plus GNU extensions.  I ask because the GNU compiler separates this from regular C99, while other compilers like XL don't.  If you run xlc -qlanglvl=c99, it supports inline assembly, but if you run gcc -std=c99, it does not.  You have to run with std=gnu99.
> 
> I *suspect* that most people will prefer gnu99 by default, as the lenient mode is the default for both gcc and xlc, but I could be conjecturing too far here.
> 
> My suggestion would be to have an option like "CMAKE_STRICT_C_DIALECT=TRUE" that says to also turn off support for compiler-specific extensions if possible, e.g.:
> 	gcc:		-std=c99
> 	xlc:		-qnoasm -qlanglvl=c99
> 
> and stick to the standard, but prefer the more lenient mode by default e.g.:
> 	gcc:		-std=gnu99
> 	xlc:		-qlanglvl=c99

IMO, such a dialect strictness flag would be problematic due to the
expectations the users may have and the undesired effects that may
occur. E.g., does strict C99 mean that C89 constructs are rejected?
For this, one needs to pass "-pedantic-errors" or the like to GCC,
but I'd have objections to enable such a flag automatically since
the user might prefer a non-pedantic behavior elsewhere. Further-
more, what does strict C99 mean for compilers which don't fully
support this standard, like MSVC as Hendrik has remarked in the
meantime? Finally, the more flags one includes in the CMAKE_C_
DIALECT_C99 variable, the higher is the probability to cause
contraries to the user's intention. Suppose one wants to have
strict C99 *plus* inline assembly with XL C; one might initially
configure the project with "CFLAGS=-qasm cmake ..." which makes the
"-qasm" switch appear on the command line before the "-qnoasm" one
enabled by CMAKE_C_DIALECT_C99 via the COMPILE_FLAGS property, e.g.,
so inline assembly is finally disabled, though requested explicitly.
With __language_dialects(), one could edit the dialect flags in the
cache taking "-q[no]asm" into account before the configuration starts.

The approach with __language_dialects() is meant as a simple method to
pass simple options to the compiler in order to express the need for a
specific language dialect via a simple compiler-independent interface,
but one should not aim at a more fine-grained control; regarding the
different compilers with their countless command line options, this
would be nearly impossible, even on the limited realm of language
dialects. BTW, with GNU C, one would call __language_dialects()
including "GNU99 -std=gnu99" and the like, of course, since the
user certainly expects that GNU compilers support GNU dialects.

>> This turns out to be a simple and promising approach that
>>
>> - provides the developers with platform/compiler-independent variables
>>  to check if the compiler accepts a certain dialect and to enable it,
> 
> Yes.  This is great.
> 
>> - places the compiler-specific dialect flags in the compiler-specific
>>  files in the Modules/Compiler directory where they obviously belong,
> 
> Excellent.
> 
>> - doesn't require complicated modifications in the Modules directory.
> 
> Also great.
> 
>> If you like this idea, feel free to add it to the feature request Todd
>> has filed in the meantime. However, while this approach is independent
>> of the dialects a compiler actually supports, be aware that mixed C89/
>> C90 projects to be built with CMake need *one* compiler which masters
>> C89 *and* C99, and that's not guaranteed for all of them.
> 
> I'm not sure what a good way around this would be, given the current internals of CMake.  I would personally like to see CMake support multiple compilers like this for other reasons (mixing cross-compiled and non-cross-compiled builds) but I don't think that will happen in the near future and I'm not sure what a clean way to support it would be.

As I've written in my reply to Owen's posting, one might use a wrapper
script which scans its arguments for a home-brewed dialect switch and
accordingly invokes different compilers, but this approach certainly
bears limitations and is only good for project-specific solutions, at
most site-specific ones. For the moment, mixed-dialect projects seem
to be built best with a multi-dialect compiler, and any compiler which
does not support all required dialects should be rejected as unsuitable.
CMAKE_<LANG>_DIALECT_<DIALECT> could be quite helpful in this regard, too.

Regards,

Michael

>>> It's also horrible to encumber the poor user just trying to build your
>>> project with needing to know whether it is written in C99 or whatever else,
>>> nor with how to make their compiler deliver that dialect.
>>
>> Once the CMake-detected or user-specified compiler isn't suitable for
>> the project, the user is in charge of choosing another one, and this
>> might happen quite quickly; it's sufficient that the compiler is not
>> in the PATH or unusually named. Then, the user must know whether the
>> project needs a C and/or C++ and/or Fortran compiler, and where it's
>> located. In such a situation, the need to know that a C99 compiler
>> is required does not make any further difference to the user, IMO.
> 
> This seems in line with the current level of knowledge effort required to build a CMake project.  There is an effort to get things right automatically, but if you want a specific compiler and things can't be guessed, you're on your own.  I agree on this one.
> 
>> In order not to be misunderstood: Of course, I appreciate measures
>> making the user's life easier, but I don't believe that choosing a
>> suitable compiler via the CC environment variable is something that
>> means an excessive demand for anyone.
> 
> I agree with this, too.  I just think that it's possible to do better in this case.  It's these kinds of convenience features that make CMake a pleasant build system.  Thanks for putting the patch together -- I think we should replace my initial feature request with this because your patch is far more comprehensive.
> 
> -Todd


More information about the CMake mailing list