[CMake] Overriding C compiler flags in CMakeLists files

Andrei Buzgan andrei.buzgan at gmail.com
Thu Aug 18 01:57:49 EDT 2011


Hello everyone,

Thanks for your answers.

I managed to obtain what I want using Michael's proposal to set up each
module with different compiler flags as a static library.
Here's what I did, maybe someone else needs this information:

Using set_source_files_properties() in the top level CMakeLists.txt with no
static libraries correctly appends compiler flags and definitions to the
existing ones. This was not good for my situation since duplicating some
flags and definitions will not give the expected result: e.g. top level -U
<define> will override the effect of a -D <define> in the leaf
CMakeLists.txt file and for some compiler flags I had no option to disable
them if they were already set, but this is just a drawback of the compiler
kit I'm using.

*Working solution:*
*Top level CMakeLists.txt contains:*

*add_executable( ${USER_SUBPROJECT_NAME} ${USER_SOURCES} )*
where USER_SOURCES is the list of source files with global compiler flags
and definitions.

*target_link_libraries( ${USER_SUBPROJECT_NAME}
        lib1
        lib2
        lib3
    )*
where lib1 lib2 lib3 will be defined in leaf CMakeLists.txt files.

*In leaf CMakeLists.txt files:*
*add_library( lib STATIC source.c )*
*set( USER_LOCAL_DEFINES
        "DEF1"
        "DEF2"
        "DEF3"
    )*
# without -D prefix.
*set_source_files_properties( source.c PROPERTIES COMPILE_FLAGS "-flag1
-flag2 -flag3" )
set_source_files_properties( source.c PROPERTIES COMPILE_DEFINITIONS
"${USER_LOCAL_DEFINES}" )*

the last line combined with set of USER_LOCAL_DEFINES will give the correct
format since property COMPILE_DEFINITIONS expects a list separated by
semicolons and automatically add -D prefix to each element.

Also, COMPILE_DEFINITIONS, as it's working now, does not permit to add
undefines so probably I'll give up to this format and use only COMPILE_FLAGS
property with explicit -D and -U prefixed macros as regular compiler flags.

Because of the non-standard compiler kit a static library does not need
processing by ar.exe and ranlib.exe found and configured by CMake
automatically out of MinGW. So I had to override some CMake configuration in
the manually created Platform-Compiler-Lang.cmake file I'm using:

*In Platform-Compiler-Lang.cmake:*

#Linking command
*set( CMAKE_C_LINK_EXECUTABLE
        "${USER_CONFIG_LINKER} <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o
<TARGET>"
        "${USER_CONFIG_CONVERTER} <TARGET> -o <TARGET>"
    )*

<LINK_LIBRARIES> will contain all the libraries declared in leaf
CMakeLists.txt files. <OBJECTS> will contain all the regular compiled
sources declared in set_executable() statement.
${USER_CONFIG_LINKER} is a custom variable used to call the linker
executable and override the ld.exe found by CMake. It is initialize in
Toolchain.cmake file like:

*find_program( USER_CONFIG_LINKER linker )*

The second and last command in CMAKE_C_LINK_EXECUTABLE is the converter
invocation, which specifically for this compiler kit converts the .abs
linked file (which contains also debug info) to plain hex executable ready
to be burned in flash - also a feature specific to my compiler kit.

*Second, also in Platform-Compiler-Lang.cmake file I added the following
lines:*

*set( CMAKE_C_ARCHIVE_CREATE "${CMAKE_COMMAND} -E copy <OBJECTS> <TARGET>" )
*

in order to create the library target by simply copy the object file in the
"archive library" step. Basically what I'm using are custom compiled object
files and not "real" libraries.

The second line is:

*set( CMAKE_C_ARCHIVE_FINISH "" )*

used to disable ranlib.exe usage in the second step of library creation.

That's it. Maybe not the most elegant solution for embedded cross-compiling
with custom flags for each source file but it seems to work well.

Andrei



On Tue, Aug 9, 2011 at 6:28 PM, Michael Hertling <mhertling at online.de>wrote:

> On 08/09/2011 04:43 PM, Michael Wild wrote:
> > Well, directory properties are used by _targets_ defined in that
> > directory. It doesn't matter where the sources are located.
> >
> > Michael
>
> Additionally, setting a source property in the leaf CMakeLists.txt
> files as it has been suggested in this thread earlier wouldn't work
> also since such properties apply to source files for targets defined
> in the same CMakeLists.txt only. As the target is defined in the top-
> level CMakeLists.txt, any source property set in a subdirectory's
> CMakeLists.txt won't take effect.
>
> To revisit Andrei's concern: As your target is defined in the top-level
> CMakeLists.txt, only settings which are valid in this file apply to the
> My_Exec target, i.e. they must be defined in this CMakeLists.txt since
> there's no superior one to inherit from. Thus, you should imply source
> file properties, e.g. COMPILE_FLAGS, on the source files from within
> the top-level CMakeLists.txt. As an alternative, in each of your sub-
> directories, you might define a static library target built from the
> respective source files and link your top-level target against these
> libraries, provided your toolchain supports it. In this manner, you
> can define fine-grained target/directory-specific compilation flags,
> and linking against a static library is usually quite the same as
> incorporating the library's object files immediately.
>
> 'hope that helps.
>
> Regards,
>
> Michael
>
> > On 08/09/2011 04:36 PM, Tim Gallagher wrote:
> >> Interesting -- I guess this is sort of off topic from the original post,
> but that brings up a question:
> >>
> >> How does setting the COMPILE_DEFINITIONS on the directory work then? I
> was under the impression (not having tried it) that those definitions would
> only be added when compiling files contained in the directory. I assumed
> COMPILE_FLAGS could, if it existed, operate the same way.
> >>
> >> Tim
> >>
> >> ----- Original Message -----
> >> From: "Michael Wild" <themiwi at gmail.com>
> >> To: cmake at cmake.org
> >> Sent: Tuesday, August 9, 2011 10:32:58 AM
> >> Subject: Re: [CMake] Overriding C compiler flags in CMakeLists files
> >>
> >> On Tue 09 Aug 2011 04:28:51 PM CEST, Tim Gallagher wrote:
> >>> In your leaf CMakeLists.txt, try doing:
> >>>
> >>> set_source_files_properties(${SOURCE_FILES} PROPERTIES COMPILE_FLAGS
> >>> ${LOCAL_COMPILE_FLAGS})
> >>>
> >>> where ${SOURCE_FILES} is a list of the files in the directory and
> >>> ${LOCAL_COMPILE_FLAGS} is the list of flags for those files.
> >>>
> >>> Ideally you would want to set this for the entire directory, but
> >>> according to the documentation, the COMPILE_FLAGS property doesn't
> exist
> >>> for directories.
> >>>
> >>> Tim
> >>>
> >>
> >> Setting a directory property wouldn't help, since the directory
> >> property is inherited by the target, not the source files. And since
> >> the target lives in the top-level CMakeLists.txt file, the directory
> >> properties wouldn't come into play at all.
> >>
> >> Michael
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the CMake FAQ at:
> http://www.cmake.org/Wiki/CMake_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20110818/164f6316/attachment.htm>


More information about the CMake mailing list