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”:
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:
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:
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