[CMake] What does `cross-platform' mean?

Jed Brown jed at 59A2.org
Mon Nov 10 05:47:29 EST 2008


On Sun 2008-11-09 17:55, Bill Hoffman wrote:
> OK, so you have version of libraries that are not in default locations,  
> how is any build system supposed to find stuff like this?

Of course not automatically, but with minimal hinting.  Ideally the user
runs CMake and sees one visible cache entry indicating the root at which
packages were found.  If the user notices that FOO_DIR is not the
intended version, they would change that cache variable and reconfigure.
In the current scheme, the module writer needs to do significant work to
get this behavior.  I think Eric's suggestion is much nicer than my
FIND_PACKAGE_MULTIPASS macro, but it needs language support.

My point about CC and friends is that there are often standard
environment variables for setting this stuff.  I think it should be
possible to select the version of packages with one variable.  For Qt4,
this is the qmake executable, for PETSc, it is (by convention) PETSC_DIR
and PETSC_ARCH.  With most packages, if the wrong version is found by
default, the user is required to edit all the advanced cache entries or
to delete the cache manually and try again with the correct variable
set.

...

> There is some code inside CMake that does library path searching.  It  
> might make sense to have a command that parses link lines and finds the  
> libraries.  I am thinking a new command might be a good idea.

I agree, it's really painful to do this in a robust way in CMake.  The
command needs significant semantics (like understanding nested shell
quoting) to handle pathological inputs (which mine doesn't).  For
instance, if the library makefile system sets

FOO_CFLAGS = -I/path/to/foo/include -DBAD='"Some -Ipathological string"'

it would be nice to parse this correctly.  I know this looks like
over-engineering, but logic to parse this correctly must exist somewhere
in CMake already.

...

> So, what does BuildSystem do to handle this?   Is there anything that  
> can be learned?

It's not elegant.  It always assumes that the entire dependency graph
needs to be linked (as with static libraries).  The analogue of Find*
modules recognize this and behave accordingly.  Component Foo can always
be selected using

  --with-foo-dir=/path/to/foo

or, if your layout is sufficiently pathological (i.e. not something the
module checks), by using

  --with-foo-include=/path/to/include/foo-1.2               \
  --with-foo-dir="-L/path/to/lib64/foo-1.2 -lfoo -lfoocore"

There is no cached state, so every time you run configure, everything is
found again.  If anything doesn't work, the configure step fails with an
error message and a log file.  This means there can never be stale cache
entries, but it also makes the reconfigure step slow.  If you're trying
to determine how to use a library which is not checked early in the
configuration process, it may take unacceptably long to report that the
options you gave don't work.  Upon successful configure, a summary of
which versions of all libraries are being used is printed on stdout and
a python script is written at

  ${PETSC_DIR}/${PETSC_ARCH}/conf/reconfigure-${PETSC_ARCH}.py

which contains all the needed options.  Running this script is similar
to running CMake after the CMakeLists.txt has been changed.

I think the semantics of BuildSystem (always recognizes --with-foo-dir,
never has stale cache) are good.  It is immediately clear to the user
which version is being used.  When a cache is present (which I think we
all agree is a good thing) deciding when tests need to be rerun is
tricky.  If the user sets variables that change how anything is
resolved, the test needs to be rerun.  See my hack
MULTIPASS_C_SOURCE_RUNS which forces everything to be rerun each time it
is called.  Encapsulating the environment of a test is a hard problem,
but a false positive is much better than a false negative.  That is,
it's better to rerun a test that didn't really need to be rerun than to
rely on a stale cache entry.  I sometimes find myself repeatedly running
this

  $ rm -r * && cmake .. -DFOO_VAR=blah

to guarantee that the cache is not stale and all necessary tests are
actually run.

...

> 1. CMake needs a command to parse compiler link lines that may come from  
> pkg-config, makefile fragments or some other config file.  The parsing  
> should act like a linker, and give the results in full paths to the  
> libraries.  This can be done ad-hoc and is done by some folks now using  
> custom macros.  We should be able to use some of the internal CMake  
> library path resolution code to do this.

Great.

> 2. CMake needs a way to easily chain variables together so that you can  
> clear stuff out if a dependent variable is changed by the user.  So, if  
> you have MY_PATH_TO_TOOL=/path/to/tool, and it changes to  
> /new/path/to/tool, then all the libraries that where found using  
> MY_PATH_TO_TOOL should be reset and rediscovered.  Currently, this is  
> done ad-hoc in CMake, for example Clinton just added something to the  
> FindQt4 that will reset all the qt variables if the qmake one is  
> changed.   However, this issue has come up more than once and needs a  
> more consistent API for dealing with the issue.

I think Eric's suggested syntax would be nice.

> 3. How to best find libraries and headers not is system locations.  
> Currently, CMake uses environment variables like PATH,  
> CMAKE_LIBRARY_PATH, etc to do this.  I have not seen a new suggestion in  
> this area.  Do you have one?

PATH and CMAKE_LIBRARY_PATH are sledgehammers.  It's nice to be able to
do this on a per-package level.  Something like setting FOO_DIR as an
environment variable or modifying the public cache entry by this name.
With wrapper compilers, the path to the wrapper is a good choice.

The module should be able to guarantee that the cache entry really does
indicate where the library is found (assuming the advanced entries like
FOO_LIBRARIES haven't been manually modified) rather than just a search
path for the library.

That is, if I specify -DFOO_DIR=/path/to/foo and Foo could not be found
there (maybe I should have spelled it -DFOO_DIR=/path/to/foo-1.2) then
the module should not silently fall back on /usr/lib/libfoo.so.

Any ideas on how to make these semantics accessible to module writers
without a lot of custom effort?

Jed
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://www.cmake.org/pipermail/cmake/attachments/20081110/9eb9ed3d/attachment.pgp>


More information about the CMake mailing list