Discussion:
[CMake] #cmakedefine and the #if vs #ifdef argument
Hostile Fork
2009-06-11 21:32:52 UTC
Permalink
Hello list!

As a learning exercise, I am adding CMake and CTest to a small open-
source library I made which currently has no build system:

http://hostilefork.com/nstate/
http://hostilefork.com/nocycle/

For the first step, I have been applying the "configure_file"
methodology to this header:

http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb991074c8eb3fd/NocycleSettings.hpp

( Following these directions: http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks
)

It seems the #cmakedefine lines are replaced with one of these two
cases:

#define VAR_THAT_IS_ON
/* #undef VAR_THAT_IS_OFF */

However... in the past I have been persuaded by the argument that the
use of #if is superior to #ifdef for conditional compilation.
( Roddy's comment here on StackOverflow summarizes the advantages
pretty well: http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersafer
)

Is it possible to get CMake to produce something more like:

#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0

There are other questions I have lined up. :) But I'll start with
just that one, and if anyone wants to be proactive offer advice/
pointers/urls based on the existing source... please jump in!

Thanks!
---Brian
Pau Garcia i Quiles
2009-06-11 21:47:57 UTC
Permalink
Post by Hostile Fork
Hello list!
As a learning exercise, I am adding CMake and CTest to a small open-source
       http://hostilefork.com/nstate/
       http://hostilefork.com/nocycle/
For the first step, I have been applying the "configure_file" methodology to
 http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb991074c8eb3fd/NocycleSettings.hpp
http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks )
       #define VAR_THAT_IS_ON
       /* #undef VAR_THAT_IS_OFF */
However... in the past I have been persuaded by the argument that the use of
#if is superior to #ifdef for conditional compilation.  ( Roddy's comment
http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersafer )
       #define VAR_THAT_IS_ON 1
       #define VAR_THAT_IS_OFF 0
There are other questions I have lined up.  :)  But I'll start with just
that one, and if anyone wants to be proactive offer advice/pointers/urls
based on the existing source... please jump in!
You can do something like in your headerfile.h.cmake :

#define VAR_THAT_IS_ON @VAR_THAT_IS_ON@
#define VAR_THAT_IS_OFF @VAR_THAT_IS_OFF@

If you call CMake with 'cmake -DVAR_THAT_IS_ON=1 -DVAR_THAT_IS_OFF=0',
it will produce:

#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0

Problem is, if CMake is invoked with anything else (for instance
'cmake -DVAR_THAT_IS_ON=foo -DVAR_THAT_IS_OFF=bar' ), it will produce:

#define VAR_THAT_IS_ON foo
#define VAR_THAT_IS_OFF bar

You'd need to do something more complex (using IF-THEN-ELSE) in CMake
to make sure only '1' and '0' are the values used for the defines.
--
Pau Garcia i Quiles
http://www.elpauer.org
(Due to my workload, I may need 10 days to answer)
Hostile Fork
2009-06-12 02:02:43 UTC
Permalink
Post by Pau Garcia i Quiles
If you call CMake with 'cmake -DVAR_THAT_IS_ON=1 -DVAR_THAT_IS_OFF=0',
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Hello Pau, thanks for the quick response...

This approach would work if I were using STRING. However, the
variables in question were created using "option", and are
BOOL...which seems preferable. Yet this gives rise to some very
unusual behavior in how they substitute using @***@.

Anything equivalent to 'off' (e.g. "0", "off", "falSE", "NO") produces
an all-caps "OFF". So that means I get:

#define VAR_THAT_IS_OFF OFF

If using the command line ("-DVAR_THAT_IS_ON=[stuff]"), then any stuff
equivalent to 'on' (e.g. "1", "Yes", "oN", "True") is forced to ON.
So that seemed pretty symmetric:

#define VAR_THAT_IS_ON ON

I was tempted to just '#define OFF 0' and '#define ON 1' in my file
and move on. But when using the interactive mode ("cmake -i") it did
something unusual... it preserved the specific string you had used to
specify 'on'. So you get a wide variety of possibilities, such as:

#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_ON on
#define VAR_THAT_IS_ON On
#define VAR_THAT_IS_ON oN
#define VAR_THAT_IS_ON ON
#define VAR_THAT_IS_ON yes
#define VAR_THAT_IS_ON Yes
#define VAR_THAT_IS_ON yEs
...
#define VAR_THAT_IS_ON true
...
#define VAR_THAT_IS_ON TRUe
#define VAR_THAT_IS_ON TRUE

(Note: strings that aren't allowed signifiers of ON/OFF are treated as
off. So entering "banana" in the interactive mode will get you an all-
caps OFF in the substitution.)

The command line does not do the case standardization for variables
declared as "BOOL", only those made using option. So if you say:

set(VAR_BOOL OFF CACHE BOOL "A boolean variable")

Then supplying '-DVAR_BOOL=oN' on the command line will substitute to
'oN' and not 'ON'. Changing this to an option gets the normalization
back:

option(VAR_BOOL "A boolean variable")


==> SOURCE INVESTIGATION <==

Since I'm curious about CMake and understanding what it does, I looked
into the source. I gather the short answer is that any current
appearance of standardization for boolean substitution is unintentional.

I'm not sure how valuable establishing such a standard would be...
since it could apply only to 'option' variables (and those 'set'
variables that were declared to be in the cache and BOOL). Though it
doesn't look too hard to do. All cached variables seem to be added
through cmCacheManager::AddCacheEntry:

http://public.kitware.com/cgi-bin/viewcvs.cgi/Source/cmCacheManager.cxx?revision=1.112&root=CMake&view=markup

So a quick hack would be to change the start of that function to:

CacheEntry& e = this->Cache[key];
e.Properties.SetCMakeInstance(this->CMakeInstance);
if ( value )
{
if ( type == cmCacheManager::BOOL )
e.Value = cmSystemTools::IsOn(value) ? "ON" : "OFF";
else
e.Value = value;
e.Initialized = true;
}
else
...

But you're still stuck with having to #define ON and OFF... which I
don't particularly care for. So perhaps a parameter to configure_file
would help? It could tell CMake to turn '#cmakedefine
VAR_THAT_IS_OFF' into '#define VAR_THAT_IS_OFF 0'. Or rather than a
parameter, there might just a new keyword (such as '#cmakedefine01
VAR_THAT_IS_OFF'.)

Any thoughts?

---Brian
Mike Jackson
2009-06-12 02:39:51 UTC
Permalink
Sometimes I'll do something like the following:

set (FOO_SOMETHING_SUPPORT 0)
OPTION (USE_SOMETHING "blah blah" ON)
if (USE_SOMETHING)
set (FOO_SOMETHING_SUPPORT 1)
endif()

then in my .h.in file I'll have:

#define FOO_SOMETHING_SUPPORT @ FOO_SOMETHING_SUPPORT@

That is just one way to do what you want. Others will chime in with more ideas.

Mike
Post by Hostile Fork
Post by Pau Garcia i Quiles
If you call CMake with 'cmake -DVAR_THAT_IS_ON=1 -DVAR_THAT_IS_OFF=0',
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Hello Pau, thanks for the quick response...
This approach would work if I were using STRING.  However, the variables in
question were created using "option", and are BOOL...which seems preferable.
 Yet this gives rise to some very unusual behavior in how they substitute
Anything equivalent to 'off' (e.g. "0", "off", "falSE", "NO") produces an
       #define VAR_THAT_IS_OFF OFF
If using the command line ("-DVAR_THAT_IS_ON=[stuff]"), then any stuff
equivalent to 'on' (e.g. "1", "Yes", "oN", "True") is forced to ON.  So that
       #define VAR_THAT_IS_ON ON
I was tempted to just '#define OFF 0' and '#define ON 1' in my file and move
on.  But when using the interactive mode ("cmake -i") it did something
unusual... it preserved the specific string you had used to specify 'on'.
       #define VAR_THAT_IS_ON 1
       #define VAR_THAT_IS_ON on
       #define VAR_THAT_IS_ON On
       #define VAR_THAT_IS_ON oN
       #define VAR_THAT_IS_ON ON
       #define VAR_THAT_IS_ON yes
       #define VAR_THAT_IS_ON Yes
       #define VAR_THAT_IS_ON yEs
       ...
       #define VAR_THAT_IS_ON true
       ...
       #define VAR_THAT_IS_ON TRUe
       #define VAR_THAT_IS_ON TRUE
(Note: strings that aren't allowed signifiers of ON/OFF are treated as off.
 So entering "banana" in the interactive mode will get you an all-caps OFF
in the substitution.)
The command line does not do the case standardization for variables declared
       set(VAR_BOOL OFF CACHE BOOL "A boolean variable")
Then supplying '-DVAR_BOOL=oN' on the command line will substitute to 'oN'
       option(VAR_BOOL "A boolean variable")
==> SOURCE INVESTIGATION <==
Since I'm curious about CMake and understanding what it does, I looked into
the source.  I gather the short answer is that any current appearance of
standardization for boolean substitution is unintentional.
I'm not sure how valuable establishing such a standard would be... since it
could apply only to 'option' variables (and those 'set' variables that were
declared to be in the cache and BOOL).  Though it doesn't look too hard to
do.  All cached variables seem to be added through
 http://public.kitware.com/cgi-bin/viewcvs.cgi/Source/cmCacheManager.cxx?revision=1.112&root=CMake&view=markup
       CacheEntry& e = this->Cache[key];
       e.Properties.SetCMakeInstance(this->CMakeInstance);
       if ( value )
               {
               if ( type == cmCacheManager::BOOL )
                       e.Value = cmSystemTools::IsOn(value) ? "ON" : "OFF";
               else
                       e.Value = value;
               e.Initialized = true;
               }
       else
               ...
But you're still stuck with having to #define ON and OFF... which I don't
particularly care for.  So perhaps a parameter to configure_file would help?
 It could tell CMake to turn '#cmakedefine VAR_THAT_IS_OFF' into  '#define
VAR_THAT_IS_OFF 0'.  Or rather than a parameter, there might just a new
keyword (such as '#cmakedefine01 VAR_THAT_IS_OFF'.)
Any thoughts?
---Brian
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
http://www.cmake.org/Wiki/CMake_FAQ
http://www.cmake.org/mailman/listinfo/cmake
Mike Jackson
2009-06-12 02:40:51 UTC
Permalink
in your cmakelists.txt files use the following:

set (VAR_THAT_IS_ON 1)
set (VAR_THAT_IS_OFF 0)

instead of TRUE or FALSE. Means the same thing plus your configured
files will "just work".

Mike
Post by Hostile Fork
Hello list!
As a learning exercise, I am adding CMake and CTest to a small open-source
       http://hostilefork.com/nstate/
       http://hostilefork.com/nocycle/
For the first step, I have been applying the "configure_file" methodology to
 http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb991074c8eb3fd/NocycleSettings.hpp
http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks )
       #define VAR_THAT_IS_ON
       /* #undef VAR_THAT_IS_OFF */
However... in the past I have been persuaded by the argument that the use of
#if is superior to #ifdef for conditional compilation.  ( Roddy's comment
http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersafer )
       #define VAR_THAT_IS_ON 1
       #define VAR_THAT_IS_OFF 0
There are other questions I have lined up.  :)  But I'll start with just
that one, and if anyone wants to be proactive offer advice/pointers/urls
based on the existing source... please jump in!
Thanks!
---Brian
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
http://www.cmake.org/Wiki/CMake_FAQ
http://www.cmake.org/mailman/listinfo/cmake
Alexander Neundorf
2009-06-17 21:27:19 UTC
Permalink
Post by Hostile Fork
Hello list!
As a learning exercise, I am adding CMake and CTest to a small open-
http://hostilefork.com/nstate/
http://hostilefork.com/nocycle/
For the first step, I have been applying the "configure_file"
http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb9910
74c8eb3fd/NocycleSettings.hpp
http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks )
It seems the #cmakedefine lines are replaced with one of these two
#define VAR_THAT_IS_ON
/* #undef VAR_THAT_IS_OFF */
However... in the past I have been persuaded by the argument that the
use of #if is superior to #ifdef for conditional compilation.
( Roddy's comment here on StackOverflow summarizes the advantages
http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersafer
)
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Did you try using
#cmakedefine01 VAR_THAT_IS_ON
I think this should do what you want.

Alex
Michael Wild
2009-06-18 06:03:36 UTC
Permalink
Post by Alexander Neundorf
Post by Hostile Fork
Hello list!
As a learning exercise, I am adding CMake and CTest to a small open-
http://hostilefork.com/nstate/
http://hostilefork.com/nocycle/
For the first step, I have been applying the "configure_file"
http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb9910
74c8eb3fd/NocycleSettings.hpp
http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks )
It seems the #cmakedefine lines are replaced with one of these two
#define VAR_THAT_IS_ON
/* #undef VAR_THAT_IS_OFF */
However... in the past I have been persuaded by the argument that the
use of #if is superior to #ifdef for conditional compilation.
( Roddy's comment here on StackOverflow summarizes the advantages
http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersafer
)
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Did you try using
#cmakedefine01 VAR_THAT_IS_ON
I think this should do what you want.
Alex
Now, that is useful! Sadly, it is undocumented and I never found it;
this would have saved me quite some time...

Attached patch extends the doc to mention this feature.
Michael Wild
2009-06-22 19:04:11 UTC
Permalink
Post by Michael Wild
Post by Alexander Neundorf
Post by Hostile Fork
Hello list!
As a learning exercise, I am adding CMake and CTest to a small open-
http://hostilefork.com/nstate/
http://hostilefork.com/nocycle/
For the first step, I have been applying the "configure_file"
http://github.com/hostilefork/nocycle/blob/1ac238aea7af9e02f3a49f0c7eb9
910 74c8eb3fd/NocycleSettings.hpp
http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks )
It seems the #cmakedefine lines are replaced with one of these two
#define VAR_THAT_IS_ON
/* #undef VAR_THAT_IS_OFF */
However... in the past I have been persuaded by the argument that the
use of #if is superior to #ifdef for conditional compilation.
( Roddy's comment here on StackOverflow summarizes the advantages
http://stackoverflow.com/questions/135069/ifdef-vs-if-which-is-bettersaf
er )
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Did you try using
#cmakedefine01 VAR_THAT_IS_ON
I think this should do what you want.
Alex
Now, that is useful! Sadly, it is undocumented and I never found it;
this would have saved me quite some time...
Attached patch extends the doc to mention this feature.
PLease put it in the bug tracker.
Thanks
Alex
Done: http://public.kitware.com/Bug/view.php?id=9189

Michael

Hostile Fork
2009-06-20 06:13:09 UTC
Permalink
Post by Hostile Fork
#define VAR_THAT_IS_ON 1
#define VAR_THAT_IS_OFF 0
Did you try using
#cmakedefine01 VAR_THAT_IS_ON
I think this should do what you want.
Thanks Alex! This seems to work, and it's exactly what I would have
suggested (down to the name!)

But I'm concerned that I didn't find this in the documentation. I did
this search on Google:

http://www.google.com/#hl=en&safe=off&q=cmakedefine01+site
%3Acmake.org&aq=f&oq=&aqi=&fp=itFkAGfC3t0

...and noticed that someone responded to a question you asked about
why a wiki tutorial did *not* mention #cmakedefine01:

"This feature has been removed again (it was never in a release
version > AFAIK)."

There are very few hits there. So...is there a version # of Cmake I
should require to use this? Is it guaranteed to stay in going forward?

Thanks!
---Brian

http://hostilefork.com
Loading...