Skip to content
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

Build fixes #74

Merged
merged 7 commits into from
Jan 19, 2022
Merged

Build fixes #74

merged 7 commits into from
Jan 19, 2022

Conversation

plopezrios
Copy link
Collaborator

Fixes to get cmake to work as advertised and to suppress gfortran 11 warnings

This includes:
* Declare generated source files in include/ as GENERATED in
  TREXIO_DEVEL mode.
* Generate include/config.h with version components from project
  delcaration, and for good measure have src/templates_front/build.sh
  set version components to 0 if not present.
This includes:
* Define kind of arguments of bind(C) procedures using the relevant C
  types provided by iso_c_binding.
* Replaced "call exit(1)" with "error stop 1".
* Fixed a couple of implicit type conversions between 4-/8-byte
  integers.

The first two fix compilation of the Fortran module with -std=f2008.
@scemama
Copy link
Member

scemama commented Jan 19, 2022

Thanks Pablo!

Copy link
Member

@q-posev q-posev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for these fixes @plopezrios !

I have only one suggestion for the CMake part and one comment regarding the use c_long in the Fortran interface.

src/CMakeLists.txt Outdated Show resolved Hide resolved
src/templates_front/templator_front.org Outdated Show resolved Hide resolved
tools/generator_tools.py Outdated Show resolved Hide resolved
@plopezrios
Copy link
Collaborator Author

@q-posev @scemama do let me know if you would like any further changes

@q-posev
Copy link
Member

q-posev commented Jan 19, 2022

@plopezrios thank you for the update! Fine with me.

In the end, I think we should roll back to Fortran-specific integer(8)/(4) and same for the other types because this is more Fortran-ic, namely the user interfacing his code with TREXIO in Fortran will only see the Fortran-like types. The -Wc-binding-type warning will appear upon compilation of trexio_f.f90 module. Otherwise, I guess these warnings will appear when the user links his code with the trexio module. This is based on the assumption that Fortran users typically have arrays declared not in c_int-like types. Let me know if I missed something.

We can probably merge this PR as it is now and then roll back on the master branch.

@plopezrios
Copy link
Collaborator Author

In the end, I think we should roll back to Fortran-specific integer(8)/(4) and same for the other types because this is more Fortran-ic, namely the user interfacing his code with TREXIO in Fortran will only see the Fortran-like types.

According to the final draft of the Fortran 2008 standard (https://j3-fortran.org/doc/year/10/10-007r1.pdf ; see section 15.3 and table 15.2) using c_int64_t etc is the definition of C interoperability, and Fortran compilers should happily match Fortran types with the corresponding C types without complaining. Basically, my understanding is that this should not cause any problems.

The -Wc-binding-type warning will appear upon compilation of trexio_f.f90 module. Otherwise, I guess these warnings will appear when the user links his code with the trexio module.

The Fortran module, by construction (and according to README.md), needs to be compiled (not just linked) by the host project, so these warnings are pushed onto users. And this might be problematic, e.g., NECI by default compiles its pipeline binaries with -Werror (i.e., has a zero-warning policy) so this would have to be worked around there. In any case, I think having zero warnings compiling TREXIO can only be a good thing.

Should you still decide to revert the changes, mind that some of them (changes specifying the c_bool kind, if I remember correctly), also suppressed "GNU extension" warnings from gfortran, which would turn into errors compiling with -std=f2008 and potentially fail to compile with other compilers.

@scemama
Copy link
Member

scemama commented Jan 19, 2022

OK. so in that case the best solution is probably to generate 2 different fortran modules: one with integer(8) and one with integer(c_int64_t) and let the users choose which one they want to link in the code. What do you think?

@plopezrios
Copy link
Collaborator Author

OK. so in that case the best solution is probably to generate 2 different fortran modules: one with integer(8) and one with integer(c_int64_t) and let the users choose which one they want to link in the code. What do you think?

Just to be clear, integer(8) and integer(c_int64_t) refer to the same data type, but the latter is guaranteed to be C interoperable in a bind(C) procedure while the former is not.

Regarding the use of integer(8) itself, again according to the standard, the use of constants (like 4 and 8) is not considered portable, and instead one is encouraged to use selected_int_kind(), e.g., integer(selected_int_kind(15)) is the smallest integer kind that can represent all values ranging from -1e15 to +1e15.

@scemama
Copy link
Member

scemama commented Jan 19, 2022

Regarding the use of integer(8) itself, again according to the standard, the use of constants (like 4 and 8) is not considered portable, and instead one is encouraged to use selected_int_kind(), e.g., integer(selected_int_kind(15)) is the smallest integer kind that can represent all values ranging from -1e15 to +1e15.

Yes, I think that this move of the Fortran standard was one of the many stupid actions they took!
But I found this on Stackoverflow were they fixed it in Fortran2008:

if you don't want to specify numeric types by the required precision, but instead by the storage that they will use, Fortran 2008 provides a method. reals and integers can be specified by the number of bits of storage after using the ISO_FORTRAN_ENV module, for example, for a 4-byte (32-bit) integer:
use ISO_FORTRAN_ENV
integer (int32) :: MyInt

So I guess we should use the ISO_FORTRAN_ENV then! :-)

@plopezrios
Copy link
Collaborator Author

So I guess we should use the ISO_FORTRAN_ENV then! :-)

Yup, that would make the code portable, but it would still run into the problem that kind constants that do not come from iso_c_binding are not guaranteed to be C interoperable (even if they are the same kind) and compilers are allowed to issue warnings about this.

I don't see that there is anything to lose from having a single Fortran module with the iso_c_binding kind constants? NB, defining a Fortran-kind variable, e.g., integer(int64) :: i, and passing that as an argument declared with a C kind, e.g., integer(c_int64_t), intent(in) :: i, should work without problems.

@scemama
Copy link
Member

scemama commented Jan 19, 2022

Yup, that would make the code portable, but it would still run into the problem that kind constants that do not come from iso_c_binding are not guaranteed to be C interoperable (even if they are the same kind) and compilers are allowed to issue warnings about this.

I get it, you are right. We should use c_int64_t instead of int64 in the interface to avoid the compiler complaining.

I don't see that there is anything to lose from having a single Fortran module with the iso_c_binding kind constants? NB, defining a Fortran-kind variable, e.g., integer(int64) :: i, and passing that as an argument declared with a C kind, e.g., integer(c_int64_t), intent(in) :: i, should work without problems.

Suppose that int64 is different from c_int64_t (which is highly improbable...). Is the Fortran compiler going to do the conversion if needed? If it does it, then I agree with your last statement. If not, we will have to make functions that convert the arguments from int64 to c_int64_t before calling the C function, even if 99% of the time it is useless... :-(

@plopezrios
Copy link
Collaborator Author

Suppose that int64 is different from c_int64_t (which is highly improbable...). Is the Fortran compiler going to do the conversion if needed? If it does it, then I agree with your last statement. If not, we will have to make functions that convert the arguments from int64 to c_int64_t before calling the C function, even if 99% of the time it is useless... :-(

My main line of reasoning here is that both iso_c_binding and iso_fortran_env are provided by the Fortran compiler. One would hope that the compiler would agree with itself. But of course reality does have a habit of beating logic.. :-/

@q-posev
Copy link
Member

q-posev commented Jan 19, 2022

@plopezrios you are right about the C interoperability, I did not know about it. Thank you for the detailed explanation!

Then it seems that usingc_int64_t-like types is our best choice. Let the Fortran compilers do the rest :-)

@scemama
Copy link
Member

scemama commented Jan 19, 2022

Then it seems that usingc_int64_t-like types is our best choice. Let the Fortran compilers do the rest :-)

We all agree! I am doing a next PR for that. ready in a few minutes...

@plopezrios
Copy link
Collaborator Author

@plopezrios you are right about the C interoperability, I did not know about it. Thank you for the detailed explanation!

To be fair, I didn't know much about this either until gfortran forced me to go read about it :)

@scemama scemama merged commit 78c632f into master Jan 19, 2022
@scemama scemama deleted the build_fixes branch January 20, 2022 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants