204 lines
7.5 KiB
ReStructuredText
204 lines
7.5 KiB
ReStructuredText
|
|
|
|
FAQ for developers
|
|
==================
|
|
|
|
|
|
Which files do I need to edit?
|
|
------------------------------
|
|
|
|
Let us start with files which you normally never edit: ``CMakeLists.txt`` and
|
|
``setup`` - these are generated based on ``autocmake.yml``. Have a look in
|
|
``autocmake.yml`` and you will see all CMake files which are assembled into
|
|
``CMakeLists.txt``. You can edit those files. If you change the order of files
|
|
listed in ``autocmake.yml`` or if you add or remove CMake modules, then you
|
|
need to rerun the ``update.py`` script to refresh ``CMakeLists.txt`` and
|
|
``setup``.
|
|
|
|
|
|
Autocmake does not do feature X - I really need feature X and a setup flag --X
|
|
------------------------------------------------------------------------------
|
|
|
|
The Autocmake developers have to be very conservative and only a very limited
|
|
set of portable features of absolutely general interest become part of the
|
|
Autocmake core or an Autocmake module. Autocmake developers are also busy.
|
|
|
|
Our recommendation is to not wait for the feature to be implemented: Implement
|
|
it yourself. Here we show you how. Code your feature in a module (i.e.
|
|
``my_feature.cmake``) and place the module under ``cmake/custom/`` (the
|
|
directory name is just a suggestion, Autocmake does not enforce a directory
|
|
naming)::
|
|
|
|
cmake/custom/my_feature.cmake
|
|
|
|
And include this feature to the main ``CMakeLists.txt`` in ``autocmake.yml``
|
|
under the ``modules`` section::
|
|
|
|
modules:
|
|
- my_feature:
|
|
- source:
|
|
- custom/my_feature.cmake
|
|
|
|
Now your code is included in the main ``CMakeLists.txt``. Perhaps you also
|
|
want a setup script flag to toggle the feature::
|
|
|
|
- my_feature:
|
|
- docopt: "--enable-my-feature Enable my feature [default: False]."
|
|
- define: "'-DENABLE_MY_FEATURE={0}'.format(arguments['--enable-my-feature'])"
|
|
- source:
|
|
- custom/my_feature.cmake
|
|
|
|
Implement your ideas, test them, and share them. If your module is portable,
|
|
good code quality, and of general interest, you can suggest it to be part of
|
|
the standard set of modules or even a core feature.
|
|
|
|
|
|
How can I get a setup flag --X that toggles a CMake variable?
|
|
-------------------------------------------------------------
|
|
|
|
The following will add a ``--something`` flag which toggles the CMake variable
|
|
``ENABLE_SOMETHING``::
|
|
|
|
- my_section:
|
|
- docopt: "--something Enable something [default: False]."
|
|
- define: "'-DENABLE_SOMETHING={0}'.format(arguments['--enable-something'])"
|
|
|
|
|
|
Can I change the name of the setup script?
|
|
------------------------------------------
|
|
|
|
Yes you can do that in ``autocmake.yml``. Here we for instance change the name to "configure":
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 4
|
|
|
|
name: myproject
|
|
min_cmake_version: 3.1
|
|
default_build_type: release
|
|
setup_script: configure
|
|
language:
|
|
- Fortran
|
|
- C
|
|
- CXX
|
|
|
|
|
|
Can I prevent Autocmake from creating any front-end setup script?
|
|
-----------------------------------------------------------------
|
|
|
|
Yes, with ``setup_script: None``.
|
|
|
|
|
|
In CMake I can do feature X - can I do that also with Autocmake?
|
|
----------------------------------------------------------------
|
|
|
|
Yes. Autocmake is really just a simplistic script which helps to organize
|
|
CMake code across projects. Everything that can be done in CMake can be
|
|
realized in Autocmake.
|
|
|
|
|
|
Should I include and track also files generated by Autocmake in my repository?
|
|
------------------------------------------------------------------------------
|
|
|
|
Yes, you probably want to do that. Autocmake downloads and generates a number
|
|
of files which in principle could be generated at configure- or build-time.
|
|
However, you probably do not want the users of your code to run any Autocmake
|
|
scripts like ``update.py`` to generate the files they need to build the
|
|
project. The users of your code will run ``setup`` directly and typically expect
|
|
everything to just work (TM). Note also that the users of your code will
|
|
not need to install the pyyaml package.
|
|
|
|
|
|
The update.py script is overwriting my CMakeLists.txt and setup, isn't this bad?
|
|
--------------------------------------------------------------------------------
|
|
|
|
No, it is not as bad as it first looks. It is a feature. Normally
|
|
``CMakeLists.txt`` and ``setup`` should not contain any explicit
|
|
customization and therefore should not contain anything that could not be
|
|
regenerated. In any case you should use version control so that you can inspect
|
|
and compare changes introduced to ``CMakeLists.txt`` and ``setup`` and
|
|
possibly revert them. See also the next remark.
|
|
|
|
|
|
But I need to manually edit and customize CMakeLists.txt and setup every time I run update.py!?
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
You typically never need to manually edit and customize ``CMakeLists.txt`` and
|
|
``setup`` directly. You can introduce customizations in ``autocmake.yml``
|
|
which get assembled into the front-end scripts.
|
|
|
|
|
|
Where is a good place to list my sources and targets?
|
|
-----------------------------------------------------
|
|
|
|
As mentioned above ``CMakeLists.txt`` is not a good place because this file is
|
|
generated from ``autocmake.yml`` and your modifications would become
|
|
overwritten at some point. A good standard is to organize your sources under
|
|
``src/`` and to list your sources and targets in ``src/CMakeLists.txt``. You
|
|
can include the latter in ``autocmake.yml`` using::
|
|
|
|
- my_sources:
|
|
- source:
|
|
- https://github.com/dev-cafe/autocmake/raw/master/modules/src.cmake
|
|
|
|
If you really do not like to do it this way, you can describe your sources and
|
|
targets in a custom module in a local file and include it like this::
|
|
|
|
- my_sources:
|
|
- source:
|
|
- custom/my_sources.cmake
|
|
|
|
|
|
How can I do some more sophisticated validation of setup flags?
|
|
---------------------------------------------------------------
|
|
|
|
Sometimes you need to do more sophisticated validation and post-processing
|
|
of setup flags. This can be done by placing a module called ``extensions.py``
|
|
under ``cmake/`` (or wherever you have ``autocmake.yml``).
|
|
This file should implement a function with the following signature:
|
|
|
|
.. code-block:: python
|
|
|
|
def postprocess_args(sys_argv, arguments):
|
|
# sys_argv is the sys.argv from the setup script
|
|
# arguments is the dictionary of arguments returned by docopt
|
|
|
|
# do something here ...
|
|
|
|
return arguments
|
|
|
|
In this function you can do any validation and post-processing you like.
|
|
This function is run after the flags are parsed and before the CMake command
|
|
is run.
|
|
|
|
Example for a validation of MPI flags to the setup script:
|
|
|
|
.. code-block:: python
|
|
|
|
import sys
|
|
|
|
def contains_flag(sys_argv, flag):
|
|
return (any(x for x in sys_argv if x.startswith('--{0}='.format(flag))))
|
|
|
|
def postprocess_args(sys_argv, arguments):
|
|
|
|
# if --mpi is selected and compilers are not selected
|
|
# then compilers default to mpif90, mpicc, and mpicxx
|
|
if arguments['--mpi']:
|
|
if not contains_flag(sys_argv, 'fc') and not contains_flag(sys_argv, 'cc') and not contains_flag(sys_argv, 'cxx'):
|
|
arguments['--fc'] = 'mpif90'
|
|
arguments['--cc'] = 'mpicc'
|
|
arguments['--cxx'] = 'mpicxx'
|
|
|
|
# if one of the compilers contains "mpi" and --mpi is not selected, it is probably a user error
|
|
# in this case stop the configuration
|
|
asking_for_mpi_compiler = False
|
|
for flag in ['fc', 'cc', 'cxx']:
|
|
if contains_flag(sys_argv, 'fc'):
|
|
if 'mpi' in arguments['--fc']:
|
|
asking_for_mpi_compiler = True
|
|
if asking_for_mpi_compiler and not arguments['--mpi']:
|
|
sys.stderr.write('ERROR: you ask for an MPI compiler but have not specified --mpi\n')
|
|
sys.exit(1)
|
|
|
|
return arguments
|