Problem 1663 - The installed UseGeant4.cmake does not *extend* CMAKE_CXX_FLAGS, but fully replaces them
Summary: The installed UseGeant4.cmake does not *extend* CMAKE_CXX_FLAGS, but fully re...
Status: CLOSED FIXED
Alias: None
Product: Geant4
Classification: Unclassified
Component: cmake (show other problems)
Version: 10.0
Hardware: All All
: P5 major
Assignee: Ben Morgan
URL:
Depends on:
Blocks:
 
Reported: 2014-08-14 21:59 CEST by o.freyermuth
Modified: 2019-11-13 14:52 CET (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this problem.
Description o.freyermuth 2014-08-14 21:59:35 CEST
This was introduced with the "fix" for #1227 . 

All external projects using UseGeant4.cmake are now silently switched to use geant4-cxxflags (unless they re-add their own flags afterwards again). 

This is completely fatal: 
- All packaging systems are forcefully broken, their flags are just overridden silently. This effectively breaks packaging policy for all linux-distributions for all cmake-based packages compiling against geant4 (and using UseGeant4.cmake in the process). 
- A real-life and well-known example is geant-vmc: If I want to build it with "-std=c++11" (which is needed to compile against ROOT 6) and just configure that via ccmake / set CMAKE_CXX_FLAGS manually in the CMakeLists.txt, it is just silently overridden once UseGeant4.cmake is parsed when configuring for Geant4 => the flag is not applied and compilation against ROOT 6 fails. 
- Also, if I package geant-vmc for my distribution (Gentoo), the distributor-cflags are silently erased, breaking packaging-policy. 

An external cmake-macro should *never* replace *any* CMAKE_<LANG>_FLAGS. It is harmful enough that cmake even allows touching such variables from deeper scope. 

The "duplicate flags" issue described in #1227, however, is naturally harmless (one could also write a cmake-regexp to fix this, but I am not deep enough in this obscure syntax to offer a patch). 

As an intermediate fix I would suggest using the workaround described by the original reporter in #1227 . 

Thanks for your help and sorry if my tone was a bit rough (it really took me some time to track this down), 
Oliver
Comment 1 o.freyermuth 2014-08-14 22:20:50 CEST
Two more comments on this: 

1) 
> set(_tmp_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Geant4_CXX_FLAGS}")
(from the original report)
is actually also fatal, it should of course be
set(_tmp_CMAKE_CXX_FLAGS "${Geant4_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
to set the Geant-flags as base and allow to override them. 

As the standard-user will not add flags at all, or should only flags which he/she really needs, this is the best solution (e.g. geant-flags switch back from c++11 to c++98 again so I cannot switch there). 

2) 
The documentation in the comments in UseGeant4.cmake clearly states that the user-set flags are only extended / Geant-flags are used as known-good base-flags (as I would expected and have described in 1) ).
Comment 2 Ben Morgan 2014-08-26 13:32:48 CEST
Thanks for the report, and we'll fix this, but one comment/question:

(In reply to comment #0)
> - A real-life and well-known example is geant-vmc: If I want to build it with
> "-std=c++11" (which is needed to compile against ROOT 6) and just configure
> that via ccmake / set CMAKE_CXX_FLAGS manually in the CMakeLists.txt, it is
> just silently overridden once UseGeant4.cmake is parsed when configuring for
> Geant4 => the flag is not applied and compilation against ROOT 6 fails. 
>

If I understand correctly here, the Geant4 being linked to is compiled against
C++98, but geant-vmc is required to be compiled against C++11. If that's the case, and libstdc++ is being used then don't ABI incompatibility problems arise?
That doesn't invalidate the bug, but I think we might need to be careful about
"required" vs "recommended" flags (but I guess that in allowing CMAKE_CXX_FLAGS to take precedence it's the user's problem!).
Comment 3 o.freyermuth 2014-08-26 17:54:22 CEST
(In reply to comment #2)
> Thanks for the report, and we'll fix this, but one comment/question:
Thanks! 

> If I understand correctly here, the Geant4 being linked to is compiled against
> C++98, but geant-vmc is required to be compiled against C++11. If that's the
> case, and libstdc++ is being used then don't ABI incompatibility problems
> arise?
In principle, yes - however, all projects linking against ROOT 6 will have to switch to C++11, they are now exposing C++11-only features in their headers. 
For that reason, also geant-vmc has to use -std=c++11 if compiled against ROOT 6. 

Luckily, this is not a very strong issue; in packaging, distributions will use the same compiler version for all packages, and also in larger setups / computing clusters, the compiler-version which one uses to compile all his / her code is very likely to be the same. 
With similar compiler-version, the ABI-incompatible changes between C++98 and C++11 are minimal (although present): 
https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

At the moment, I see no other solution than living with this risk (I am still alive after many days with a very "mixed" system ;-) ). 

> That doesn't invalidate the bug, but I think we might need to be careful about
> "required" vs "recommended" flags (but I guess that in allowing CMAKE_CXX_FLAGS
> to take precedence it's the user's problem!).
Indeed ;-).
Comment 4 Ben Morgan 2014-10-20 11:54:24 CEST
Fixed on trunk, tag will go into release 10.1. Backporting to earlier releases will happen with any further patches to those versions.
Comment 5 o.freyermuth 2019-07-18 17:56:55 CEST
I can sadly still reproduce this even with 10.5.1 . Could you link the commit which should have fixed it?
Comment 6 Ben Morgan 2019-11-13 14:52:31 CET
This is now properly fixed on the git master, so will be in 10.6 due later this month. Apologies it's taken so long to resolve.