Skip to content

A Possible Solution for Compiler Flags #350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
everythingfunctional opened this issue Feb 4, 2021 · 8 comments
Open

A Possible Solution for Compiler Flags #350

everythingfunctional opened this issue Feb 4, 2021 · 8 comments
Labels
specification Issue regarding fpm manifest and model

Comments

@everythingfunctional
Copy link
Member

I have a proposed solution to the issue of how we deal with compiler flags.

I propose adding a section to the fpm.toml file where compiler flags can be specified, with the following schema.

  1. The top level table is named "compiler-flags" (I'm open to suggestions for a better name)
  2. There is a table for each compiler. If a table is not specified for a compiler, then only the default/built-in profiles are available
  3. There may be multiple tables for each compiler, whose name specifies the name of an available "profile"
  4. A profile table specifies a list of flags, as an array of strings
  5. A profile table may optionally specify a list of pairs of file and flags to be used for that file
  6. A profile only applies to a dependency if it does not explicitly override that profile
  7. Specifying a profile with the same name as one of the default profiles overrides the default flags for that profile, including for dependencies, unless they also explicitly override that profile

For example:

[compiler-flags]
[compiler-flags.gfortran]
[compiler-flags.gfortran.only_debug_symbols]
flags = ["-g"]
files = { "src/special.f90" = ["-Wall", "-Werror"] }

One can then use a specified profile like fpm build --profile only_debug_symbols. The default/built-in profiles would correspond to our existing modes, and the existing modes would be equivalent to specifying the profile explicitly. I.e. fpm build is equivalent to/implies fpm build --profile debug and fpm build --release is equivalent to/implies fpm build --profile release.

This has the following benefits:

  • A library can override the default flags if they are not appropriate, and have its users respect that
  • A project can specify some special profile in a convenient place for frequently used sets of flags
  • A project/library need not override compiler flags for every file if only one file needs something special
  • We don't need to come up with and support a coherent set of "features" supported by every compiler

I admit that the table structure seems somewhat deeply nested, so I'm open to suggestions of other schemas, but I think this covers everything that needs to be included.

P.S. If this works out I'd like to suggest an additional built-in profile - strict - that includes all possible compile and run time checking, with all warnings treated as errors. I think this is a very useful option to have, even if not utilized very often.

@awvwgk
Copy link
Member

awvwgk commented Feb 4, 2021

Too bad we can't steal a good idea from cargo here, since they never had to deal more than one compiler in their ecosystem. Requiring some deeper nesting in the package manifest seems inevitable for a good Fortran compiler support.

  1. The top level table is named "compiler-flags" (I'm open to suggestions for a better name)

I would prefer to put the profiles under the build table just to keep the root table clean.

  1. There is a table for each compiler. If a table is not specified for a compiler, then only the default/built-in profiles are available

Agreed. Using gfortran instead of gnu or gcc might be preferable for easy mapping between compiler executable name and profile, up to the moment someone is trying to compile with gfortran-9. Not sure what the best solution here would be.

  1. There may be multiple tables for each compiler, whose name specifies the name of an available "profile"

I made a similar proposal using a table of tables in #112 (comment), after thinking through different format this one seems to be the only feasible choice to support multiple compilers.

  1. A profile table specifies a list of flags, as an array of strings

How do you distinguish between compile arguments, link arguments and global arguments here?

  1. A profile table may optionally specify a list of pairs of file and flags to be used for that file

This warrants matching rules for file names, like "src/fragile/**" = ["-O1"] at some point. Not sure if arguments on per file basis should be encouraged by fpm, it will make the package manifest nearly unreadable depending on the complexity of the project.

  1. A profile only applies to a dependency if it does not explicitly override that profile
  2. Specifying a profile with the same name as one of the default profiles overrides the default flags for that profile, including for dependencies, unless they also explicitly override that profile

@everythingfunctional
Copy link
Member Author

How do you distinguish between compile arguments, link arguments and global arguments here?

Good point. I'd suggest instead of having a single flags key, have compile, link, and global keys.

@everythingfunctional
Copy link
Member Author

This warrants matching rules for file names, like "src/fragile/**" = ["-O1"] at some point. Not sure if arguments on per file basis should be encouraged by fpm, it will make the package manifest nearly unreadable depending on the complexity of the project.

Agreed. I would prefer not to encourage the use of per file compiler flags, but at some point somebody's going to "need" it, so we should have a way to do it.

@ivan-pi
Copy link
Member

ivan-pi commented Feb 9, 2021

Agreed. Using gfortran instead of gnu or gcc might be preferable for easy mapping between compiler executable name and profile, up to the moment someone is trying to compile with gfortran-9. Not sure what the best solution here would be.

Personally, the only time I use different versions of the same compiler is to find the oldest compiler version which works. In Linux I can do this easily with update-alternatives.

I can imagine problems when compiler-flags change meaning or are removed. But if a package required some specific compiler flags to make it work right, there is a high change the package was non-standard to begin with. Ideally the users would bring this up to the package maintainer who could find a workaround.

@vmagnin
Copy link
Member

vmagnin commented Feb 9, 2021

Personally, the only time I use different versions of the same compiler is to find the oldest compiler version which works. In Linux I can do this easily with update-alternatives.

Personally, I have always at least the four last versions of gfortran installed: gfortran is the latest (10), then I have gfortran-9, gfortran-8, gfortran-7, etc. When I have long computations to run, I choose the fastest one! And the latest version is not necessarily the fastest. Sometimes there is some kind of regressions considering the speed when a new major version arrives, and it improves with the following minor versions... Not huge differences but it can be up to 5 to 10%... Not negligible.

@awvwgk
Copy link
Member

awvwgk commented Feb 9, 2021

Same here, I have at least two versions of GCC available on the same system, usually gcc-7 and gcc-10, mainly for regression testing. Also, when working with conda-build the compiler name is usually something like powerpc64le-conda-linux-gnu-gfortran, which is still a gfortran compiler.

@awvwgk awvwgk added the specification Issue regarding fpm manifest and model label Feb 12, 2021
@ghost
Copy link

ghost commented Mar 1, 2021

I was trying to package the original netlib's QUADPACK as fpm package and was running into this issue: fpm is able to build everything with gfortran-7. But gfortran-10 requires the -fallow-argument-mismatch flag (I had to hardcode this flag into my local branch). All good, now the problem is that gfortran-7 doesn't recognize this flag and stops compiling. Also, I would like to write example programs without this additional flag. So, in this case I think per-compiler flags are welcome.

@ghost
Copy link

ghost commented Apr 27, 2021

It would be nice to be able to set flags for a specific operating system. For example, the linker flag -ldl may be required on Linux, and break the build if present on Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
specification Issue regarding fpm manifest and model
Projects
None yet
Development

No branches or pull requests

4 participants