Quick tour

Getting help

To get a list of available commands and help topics:

$ cmany help

To get help on a particular command (eg, build) or topic (eg, quick_tour), any of the following can be used, and they are all equivalent:

$ cmany help build
$ cmany h build             # help has an alias: h
$ cmany build -h
$ cmany build --help

Note that this text is also available as a help topic. You can read it with the help command:

$ cmany h quick_tour

Build

Consider a directory initially with this layout:

$ ls -1
CMakeLists.txt
main.cpp

The following command invokes CMake to configure and build this project:

$ cmany build .

Like with CMake, this will look for the CMakeLists.txt file at the given path (.) and place the build tree at the current working directory. If the path is omitted, CMakeLists.txt is assumed to be on the current working dir. Also, the build command has an alias of b. So the following command is exactly the same as cmany build .:

$ cmany b

When no compiler is specified, cmany chooses CMake’s default compiler. cmany’s default build type is (explicitly set to) Release. As an example, using g++ 6.1 in Linux x86_64, the result of the command above will be this:

$ tree -fi -L 2
build/
build/linux-x86_64-g++6.1-Release/
CMakeLists.txt
main.cpp

$ ls build/*/CMakeCache.txt
build/linux-x86_64-g++6.1-Release/CMakeCache.txt

Note that unlike CMake, cmany will not place the resulting build tree directly at the current working directory: it will instead nest it under ./build. Each build tree name is made unique by combining the names of the operating system, architecture, compiler+version and the CMake build type.

Configure

It was said above that the cmany build command will also configure. In fact, cmany will detect when a configure step is needed. But you can just use cmany configure if that’s only what you want to do:

$ cmany configure

Same as above: c is an alias to configure:

$ cmany c

Install

The cmany install command does what it says, and will also configure and build if needed. i is an alias to install:

$ cmany i

The install root defaults to ./install. So assuming the project creates a single executable named hello, the following will result:

$ ls -1
CMakeLists.txt
build/
install/
main.cpp

$ tree -fi install
install/
install/linux-x86_64-g++6.1-Release/
install/linux-x86_64-g++6.1-Release/bin/
install/linux-x86_64-g++6.1-Release/bin/hello

Choosing the build type

cmany uses Release as the default build type. To set a different build type use --build-types/-t. The following command chooses a build type of Debug instead of Release:

$ cmany b -t Debug

If the directory is initially empty, this will be the result:

$ ls -1 build/*
build/linux-x86_64-g++6.1-Debug/

Note that the build naming scheme will cause build trees with different build types to be placed in different directories. Apart from producing a better organization of your builds, this saves you a full project rebuild when the build type changes (and the cmake generator is not a multi-config generator like MSVC).

Choosing the compiler

cmany defaults to CMake’s default compiler. To use different compilers, use --compilers/-c. Each argument given here must be an executable compiler found in your path, or an absolute path to the compiler.

The following command chooses clang++ instead of CMake’s default compiler:

$ cmany b -c clang++

If the directory is initially empty, this will be the result:

$ ls -1 build/*
build/linux-x86_64-clang++3.9-Release/

Read more here.

Choosing build/install directories

By default, cmany creates the build trees nested under a directory build which is created as a sibling of the CMakeLists.txt project file. Similarly, the install trees are nested under the install directory. However, you don’t have to use these defaults. The following command will use foo for building and bar for installing:

$ cmany i -c clang++,g++ --build-dir foo --install-dir bar

$ ls -1 foo/ bar/
bar/linux-x86_64-clang++3.9-Release/
bar/linux-x86_64-g++6.1-Release/
bar/linux-x86_64-icpc16.1-Release/
foo/linux-x86_64-clang++3.9-Release/
foo/linux-x86_64-g++6.1-Release/
foo/linux-x86_64-icpc16.1-Release/

Note that foo and bar will still be placed under the current working directory, since they are given as relative paths. cmany also accepts absolute paths here.

Building many trees at once

The commands shown up to this point were only fancy wrappers for CMake. Since defaults were being used, or single arguments were given, the result for each command was a single build tree. But as its name attests to, cmany will build many trees at once by combining the build items. For example, to build both Debug and Release build types while using defaults for the remaining parameters, you can do the following (resulting in 2 build trees):

$ cmany b -t Debug,Release
$ ls -1 build/
build/linux-x86_64-g++6.1-Debug/
build/linux-x86_64-g++6.1-Release/

You can also do this for the compilers (2 build trees):

$ cmany b -c clang++,g++
$ ls -1 build/
build/linux-x86_64-clang++3.9-Release/
build/linux-x86_64-g++6.1-Release/

And you can also combine all of them (4 build trees):

$ cmany b -c clang++,g++ -t Debug,Release
$ ls -1 build/
build/linux-x86_64-clang++3.9-Debug/
build/linux-x86_64-clang++3.9-Release/
build/linux-x86_64-g++6.1-Debug/
build/linux-x86_64-g++6.1-Release/

Another example – build using clang++,g++,icpc for Debug,Release,MinSizeRel build types (9 build trees):

$ cmany b -c clang++,g++,icpc -t Debug,Release,MinSizeRel
$ ls -1 build/
build/linux-x86_64-clang++3.9-Debug/
build/linux-x86_64-clang++3.9-MinSizeRel/
build/linux-x86_64-clang++3.9-Release/
build/linux-x86_64-g++6.1-Debug/
build/linux-x86_64-g++6.1-MinSizeRel/
build/linux-x86_64-g++6.1-Release/
build/linux-x86_64-icpc16.1-Debug/
build/linux-x86_64-icpc16.1-MinSizeRel/
build/linux-x86_64-icpc16.1-Release/

The items that can be combined by cmany are called build items. cmany has the following classes of build items:

  • systems: -s/--systems sys1[,sys2[,...]]
  • architectures (-a/--architectures arch1[,arch2[,...]]
  • compilers (-c/--compilers comp1[,comp2[,...]]
  • build types (-t/--build-types btype1[,btype2[,...]]
  • variants (-v/--variants var1[,var2[,...]]

All of the arguments above accept a comma-separated list of items. Any omitted argument will default to a list of a single item based on the current system (for example, omitting -s in linux yields an implicit -s linux whereas in windows yields an implicit -s windows; or omitting -a in a 64 bit processor system yields an implicit -a x86_64).

cmany will generate builds by combining every build item with every other build item of different class. The resulting build has a name of the form {system}-{architecture}-{compiler}-{build_type}[-{variant}].

A variant is a build item which brings with it a collection of flags. This allows for easy combination of these flags with other build items. But note that every build item can bring specific flags with it.

Since the number of build item combinations grows very quickly and not every combination will make sense, cmany has arguments to exclude certain combinations, either by the resulting build name (with a regex) or by the names of the items that a build would be composed of. Read more about it here.

Using flags

(Full docs for flags here).

You can set cmake cache variables using --cmake-vars/-V. For example, the following command will be the same as if cmake -DCMAKE_VERBOSE_MAKEFILES=1 -DPROJECT_SOME_DEFINE=SOME_DEFINE= . followed by cmake --build was used:

$ cmany b -V CMAKE_VERBOSE_MAKEFILES=1,PROJECT_SOME_DEFINE=SOME_DEFINE=

To add preprocessor macros, use the option --defines/-D:

$ cmany b -D MY_MACRO=1,FOO=bar,SOME_DEFINE

The command above has the same meaning as if cmake -D CMAKE_CXX_FLAGS="-DMY_MACRO=1 -DFOO=bar -DSOME_DEFINE" followed by cmake --build was used.

To add C++ compiler flags, use the command line option --cxxflags/-X. To prevent these flags being interpreted as cmany command options, use quotes or single quotes:

$ cmany b -X "--Wall","-O3"      # add -Wall -O3 to all builds

To add C compiler flags, use the option --cflags/-C. As with C++ flags, use quotes to escape:

$ cmany b -C "--Wall","-O3"

Using flags per build item is easy. Instead of specifying the flags at the command level as above, specify them at build item. For example:

$ cmany b --variant 'foo: --defines SOME_DEFINE=32 --cxxflags "-Os"' \
          --variant 'bar: --defines SOME_DEFINE=16 --cxxflags "-O2"'

To be clear, the foo variant will be compiled with the preprocessor symbol named SOME_DEFINE defined to 32, and will use the -Os C++ compiler flag. In turn, the bar variant will be compiled with the preprocessor symbol named SOME_DEFINE defined to 16, and will use the -O2 C++ compiler flag. So instead of the build above, we now get:

$ ls -1 build
build/linux-x86_64-clang++3.9-Release-bar/
build/linux-x86_64-clang++3.9-Release-foo/

Note above the additional -foo and -bar suffixes to denote the originating variant.

You can make build items inherit the flags from other build items: add a @ reference to the variant you want to inherit from. For example:

$ cmany b --variant 'foo: --defines SOME_DEFINE=32 --cxxflags "-Os"' \
          --variant 'bar: @foo --defines SOME_DEFINE=16 --cxxflags "-O2"'

This will result in the bar variant having its flags specifications as --defines SOME_DEFINE=32 --cxxflags "-Os" --defines SOME_DEFINE=16 --cxxflags "-O2".

Cross-compiling

Cross compilation with cmake requires passing a toolchain file. cmany has the --toolchain option for this. This is more likely to be used as a flag of the system or architecture build type.

Building dependencies

cmany offers the argument --deps path/to/extern/CMakeLists.txt to enable building another CMake project which builds and installs the dependencies of the current project. When --deps is given, the external project is built for each configuration, and installed in the configuration’s build directory. Use --deps-prefix to specify a different install directory for the external project. Read more here.

Argument reuse

Due to the way that compilation flags are accepted, the full form of a cmany command can become big. To save you from retyping the command, you can set the CMANY_ARGS environment variable to reuse arguments to cmany. As an experimental (and buggy) feature, you can also permanently store these options in a cmany.yml project file, which should be placed side by side with the project CMakeLists.txt. You can find more about this here.

Exporting build configurations

cmany has the command export_vs, which exports the build configurations to Visual Studio through the file CMakeSettings.json (placed side by side with the project CMakeLists.txt). Read this MS blog post to discover how to use the generated file.

For code-intelligence tools requiring knowledge of the compilation commands (for example, rtags, and many other tools used with emacs), cmany offers also the argument -E/--export-compile. This argument will instruct cmake to generate the file compile_commands.json (placed in each build tree).