Standard-conforming way of doing `!DEC$ attributes dllexport`

To export subroutines for a DLL of PRIMA on Windows, I add directives like

!DEC$ attributes dllexport :: xxx

However, ifort and ifx complain that “This directive is not standard F2018.”

Question: Is there a standard conforming way to do the same?

You may give your comments under `!DEC$ attributes dllexport` is not standard Fortran · Issue #70 · libprima/prima · GitHub. Thank you.


A concrete example is as follows.

If you would like to see it in action, you may do the following.

git clone https://github.com/libprima/prima.git && cd prima &&  git checkout 6e9b334 && cd fortran/examples/cobyla/ && make itest

You will receive the following warning.

../../common/debug.F90(38): warning #7025: This directive is not standard F2018.
!DEC$ attributes dllexport :: assert
------^

Thank you for your attention.

1 Like

Problem solved. See

The compilers are just being nitpicky. How could a comment be not standard-conforming? CMake has an option relevant to this task. But I have never used it, and I do not know if it also applies to Fortran.

I recall DEF files being mentioned on Fortran Discourse before. After searching for a while I found these threads:

(@FortranFan, do you have other posts showing the usage of module-definition files?)

Here is the explanation of the solution used from the CMake file of PRIMA:

# On Windows, when building shared libs, visible functions must be explicitly listed.
# Unlike C there are no standard keywords to do this in Fortran but only compiler-specific pragmas:
# !GCC$ attributes dllexport :: bobyqa_c
# !DEC$ attributes dllexport :: bobyqa_c
# the downside is unwanted -Wattribute warnings.
# Another option is to use .def files referencing exported symbols:
# https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files?view=msvc-170
# Mangling is different between GNU and Intel/LLVM compiler families so we use a dedicated file for each.
# Symbol names can be seen in object files with the dumpbin tool (or objdump) to write a new .def:
# dumpbin /symbols cobyla.f90.obj
# 017 00000000 UNDEF  no_type       External     | COBYLA_MOD_mp_COBYLA
# x86_64-w64-mingw32-objdump -t cobyla.f90.obj
# [  4](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x000000000000218b __cobyla_mod_MOD_cobyla

It would be nice mentioning the DEF files in the Fortran-Lang mini book on Managing libraries.

I agree with @shahmoradi that throwing a warning for what is essentially a comment is questionable. It would be worth bringing this up on the Intel forum.

2 Likes

Here is the more updated comment:

I agree with @shahmoradi that throwing a warning for what is essentially a comment is questionable. It would be worth bringing this up on the Intel forum.

This has been discussed on the Intel forum. I cannot find the particular post at the moment, but I read it yesterday. Intel regards directives as “funny-looking code” rather than “funny-looking comments”. Maybe Intel colleagues here can give more insights.

Thanks.

False warnings can be annoying and give the wrong impression to users of the software.

In C++ they have introduced attributes as a way to provide additional information to the compiler, to clarify usage and silence warnings.

For example if one has an interface expecting a callback, but one of the arguments is unused, the compiler will issue warnings about an unused argument:

int foo([[maybe_unused]] int bar) { // silence warning, bar is unused
   return 42;
}

A second example is when preprocessing is involved; compiling in release mode with NDEBUG, assertions are removed, and a false warning would be issued:

void foo(int i, [[maybe_unused]] int j) {
   assert(i == j);
   // j not used further on
}

Are DEF files (hum… it sounds like death files…) used only in CMake? Or do other build systems use them? Could fpm do that?

1 Like

Module-definition or DEF files (*.def) are text files describing attributes of a dynamic-link library (DLL) (the shared library concept for the Windows operating system). They are a Windows concept not tied to CMake.

Similar to how Fortran has public and private attributes for module variables and procedures, you can think of module-definition files or the __declspec(dllexport) attribute as way to enforce storage-class attributes on items (functions, data) which are to be part of a shared library.

There are several reasons why fine-grained control of symbol visibility is needed

  • enforcing the public/private nature of an API
  • security concerns and protecting intelectual property (e.g. exposing names of internal subroutines could give away information)
  • shared library performance; i.e. the linker can discard symbols which it is sure are not used, resulting in a smaller binary object and faster startup times

The book Professional CMake: A Practical Guide - 16th Edition contains a sub-chapter on symbol visibility among other topics related to distributing libraries.

Currently fpm doesn’t support shared libraries. There is a tracking issue: Producing shared libraries · Issue #681 · fortran-lang/fpm · GitHub. The question has been asked on Discourse before: [fpm] can fpm be used to build a dynamic link library? - #6 by hkvzjal

I suppose it could export a DEF file, given a list of symbols. But you arrive at the same problem, either you introduce an an attribute !fpm$ dllexport, meaning fpm needs a parser and also has to know about the compiler name mangling, or you put this information into the fpm.toml manifest, re-inventing the DEF file syntax in the fpm manifest schema.

The Windows documentation has an article discussing the pros and cons of the different export methods: Determine Which Exporting Method to Use | Microsoft Learn

3 Likes

Here’s another post, at the Intel Fortran forum.

1 Like

PRIMA team may want to follow up again with Intel Fortran support at their forum for their current thinking and feedback on this and decide on the best course of action.

My recommendation is to avoid cluttering Fortran code with preprocessor directives as much as possible. In the case of Windows OS and dynamic (shared) library exported symbols, I recommend the Microsoft module definition .DEF file solution as shown here.

Note the warning is issued by the Intel Fortran compiler when the compiler option -stand is in effect. Additionally, Intel provides an option to suppress this specific warning via the compiler option -Qdiag-disable:7025.

module m
contains
   subroutine sub()
   !dir$ attributes dllexport :: sub
   end subroutine 
end module 
  • Note no warning when -stand is not applied:
C:\temp>ifort /c /standard-semantics /free m.f
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.10.0 Build 20230609_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.


C:\temp>ifort /c /standard-semantics /free /stand m.f
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.10.0 Build 20230609_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

m.f(4): warning #7025: This directive is not standard F2018.
   !dir$ attributes dllexport :: sub
---------^

C:\temp>
  • And the warning can be suppressed - if you so choose - using -Qdiag-disable
C:\temp>ifort /c /standard-semantics /free /stand /Qdiag-disable:7025 m.f
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.10.0 Build 20230609_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.


C:\temp>
2 Likes

Thanks you @FortranFan and @ivanpribec for the detailed comments and instructions.

I have found it: Bogus standard conformance warning for compiler directives - Intel Community, where it reads that

We had an extensive discussion about this in the past, and decided that directives are “funny-looking statements” and not comments, and that the warnings were appropriate.
[from Steven_L_Intel1, Employee]

So the opinion of Intel seems quite clear to me. I am not sure re-posting the same question would change it a lot.

Thanks.

1 Like