Skip to content

Cmake, optimization and README.md #614

@gareth-nx

Description

@gareth-nx
Contributor

Description

README.md instructs users to control compiler flags in CMake builds like this (e.g. to get "-O3"):

export FFLAGS="-O3"
cmake -B build -G Ninja -DCMAKE_MAXIMUM_RANK:String=7 -DCMAKE_INSTALL_PREFIX=$HOME/.local

However this does not have the intended effect; by default there are other options that override this optimization.

To see that this is the case, we can insert the line set( CMAKE_VERBOSE_MAKEFILE on ) near the top of CMakeLists.txt, and build with the above commands. Then the compiler commands are printed out. Copying one (for illustration) we have:

/usr/bin/gfortran  -I/home/gareth/Code_Experiments/fortran/stdlib/my_branch/stdlib/build/src/mod_files  -O3 -O2 -g -DNDEBUG -Jmod_files/   -fimplicit-none -ffree-line-length-132 -Wall -Wextra -Wimplicit-procedure -pedantic-errors -std=f2018 -c /home/gareth/Code_Experiments/fortran/stdlib/my_branch/stdlib/build/src/stdlib_bitsets_64.f90 -o CMakeFiles/fortran_stdlib.dir/stdlib_bitsets_64.f90.o

Notice how right after the "-O3", we have "-O2 -g -DNDEBUG". This is overriding the "-O3" optimization which was intended. Our documentation doesn't make this clear, and this has confused some efforts to try optimising code.

Expected Behaviour

I expected the code to have been compiled with -O3, not -O2.

The reason I noticed this is that my code was slower when linking to Cmake builds, vs Makefile builds (and hence I was getting weird performance results).

Version of stdlib

15f3270

Platform and Architecture

All

Additional Information

It seems that by default, stdlib is having CMake add the flags for a CMAKE_BUILD_TYPE=RelWithDebInfo build.

One way to work-around this issue is to have the user make up some ad-hoc BUILD_TYPE (so that the defaults are not invoked). However presumably there are some options that we really do want by default -- so the questions are:

  • What should we suggest in README.md?
  • Should any of the CMake defaults be changed?

I think it's a good idea to use CMAKE_VERBOSE_MAKEFILE=On (or suggest that option to users in the documentation). This prints out the compiler commands (so users will likely notice if they differ from what was intended).

export FFLAGS="-O3 -fno-range-check"
cmake -B build -DCMAKE_MAXIMUM_RANK=7 -DCMAKE_INSTALL_PREFIX=/home/gareth/Code_Experiments/fortran/stdlib/my_branch/stdlib/local_install_gfortran/ -DCMAKE_BUILD_TYPE=MyCustomBuild -DCMAKE_VERBOSE_MAKEFILE=On

Activity

awvwgk

awvwgk commented on Jan 3, 2022

@awvwgk
Member

Optimization levels in CMake are mainly controlled by the -DCMAKE_BUILD_TYPE, we default to NoConfig, which takes whatever CMake thinks is the best default. For most projects I prefer RelWithDebInfo for development and Release build types for profiling. We should mention the possibility to adjust this via the standard CMake option.

gareth-nx

gareth-nx commented on Jan 3, 2022

@gareth-nx
ContributorAuthor

How should we recommend that users set -DCMAKE_BUILD_TYPE ?

If they use -DCMAKE_BUILD_TYPE=Release, then I believe that will append compiler flags that include -O3. This suffers the same problem that it can override other FFLAGS (e.g. say -Ofast was specified, it would be silently overridden). So IMO it isn't the right solution (unless further qualified).

We could tell users to set -DCMAKE_BUILD_TYPE=somethingWithoutADefault if they want to prevent their compiler flags being overridden. But it could be prone to other problems (e.g. gfortran-9 users better specify -fno-range-check to avoid problems with the hash routines).

awvwgk

awvwgk commented on Jan 3, 2022

@awvwgk
Member

We could provide an overwrite file like in LFortran to purge unwanted arguments from the profiles, or at least the default profile.

gareth-nx

gareth-nx commented on Jan 3, 2022

@gareth-nx
ContributorAuthor

That sounds good.

So in the README, I imagine that, rather than explaining FFLAGS, we would say:

  • Compiler options can be controlled by modifying the file cmake/UserOverride.cmake. Separate options can be provided for different compilers, and different build types. The latter can be specified via -DCMAKE_BUILD_TYPE when compiling stdlib (common values are -DCMAKE_BUILD_TYPE=Release for builds with high optimization, and -DCMAKE_BUILD_TYPE=Debug for debugging builds).

FYI I'm traveling from tomorrow until late January (without a computer), but will follow up in a few weeks if it hasn't been addressed already.

awvwgk

awvwgk commented on Jan 3, 2022

@awvwgk
Member

I don't really want to recommend users to overwrite checked in files in our repo. Instead we should provide a way to just use FFLAGS or have users set their arguments via -DCMAKE_Fortran_FLAGS="$FFLAGS" which will overwrite the CMake defaults. We could implement some logic to always use FFLAGS to overwrite the respective CMAKE_Fortran_FLAGS_* variables for all build-types as well.

I might look into this, if I find some motivation to write needlessly trivial but lengthy stuff in CMake, because it is not available by default.

And, of course, have a nice travel.

eduardz1

eduardz1 commented on Sep 17, 2025

@eduardz1

We could provide an overwrite file like in LFortran to purge unwanted arguments from the profiles, or at least the default profile.

* definition: https://gitlab.com/lfortran/lfortran/-/blob/master/cmake/UserOverride.cmake

* usage: https://gitlab.com/lfortran/lfortran/-/blob/master/CMakeLists.txt#L3

This implementation might produce code that is not compatible across different architectures, which is not something I expect when compiling with the Release profile.

Forgive me if I am misunderstanding this issue, but I believe that suggesting by default to use NoConfig and -O3 flags instead of the Release profile is somewhat unexpected. I don't believe that handling this should be a responsibility of the Fortran stdlib at all, as it is really only a matter of familiarity with CMake. Even the default being RelWithDebInfo seems unexpected as this is not what the CMake documentations define https://cmake.org/cmake/help/v3.22/manual/cmake-buildsystem.7.html#default-and-custom-configurations. I would suggest having in the README only something along the lines of:

You can install the standard library with CMake with:

```
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
```

So that it's a single copy-paste, and you know that by default the most optimized profile will be used. The other remarks should be, IMHO, more clearly separated between the stdlib specific option and the CMake ones as the latter are really more of a "CMake tips and tricks" kind of situation.

As a last note, for development purposes, I find it useful to take advantage of CMake presets so that one can do

cmake --preset dev
cmake --build --preset dev

cmake --preset release
cmake --build --preset release

and have the first under build/dev and the second under build/release, this allows storing in the file a series of default options

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingbuild: cmakeIssue with stdlib's CMake build files

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @awvwgk@eduardz1@gareth-nx

        Issue actions

          Cmake, optimization and README.md · Issue #614 · fortran-lang/stdlib