I'd like to include a flag such as -DMY_FLAG=ONETWOTHREE in the CMake call, i.e. make .. -DMY_FLAG=ONETWOTHREE, and get the value of MY_FLAG in the fortran code. I'm using add_definitions("-DMY_FLAG=${MY_FLAG}") to pass MY_FLAG to make.
Currently, when I do something like
write(*,*) MY_FLAG
I get this compiler error:
Error: Symbol 'ONETWOTHREE' at (1) has no IMPLICIT type
Can the -D flags be cast to a type in fortran? It looks like MY_FLAG is somehow defined at compile time, but it has no type.
When using a preprocessor, the final source file must be valid Fortran. In the present situation,
write(*,*) ONETWOTHREE
is not valid because there is not variable named ONETWOTHREE.
Solutions:
Define the variable earlier:
integer ONETWOTHREE
ONETWOTHREE = 5
Do not use ONETWOTHREE but an actual value. Example for an integer:
-DMY_FLAG=123
so that the corresponding line will be
write(*,*) 123
Of course, it would be useful if you could provide us with the intention behind the usage of the preprocessor here.
Related
I know the meaning of below CMake statement:
cmake_minimum_required(VERSION 3.10)
I am just wondering what the VERSION part is syntactically?
Is it a unquoted argument? If it is an argument, there must be some other argument choices.
But according to here, it seems VERSION is the only choice for the cmake_minimum_required() command.
If so, why do we even need to specify this argument explicitly??
And according to here, this command sets the variable CMAKE_MINIMUM_REQUIRED_VERSION. Is there some kind of string concatenation here? So I can use set_minimum_required(XXX <some_value>) to sent an arbitrary variable with the name CMAKE_MINIMUM_REQUIRED_XXX to <some_value>?
ADD 1
I just tried with below statement in the CMakeLists.txt:
cmake_minimum_required(XXX 123)
And cmake complains that:
CMake Error at CMakeLists.txt:2 (cmake_minimum_required):
cmake_minimum_required called with unknown argument "XXX".
So it seems to be an argument.
But according to here for the project() command, a similar VERSION string is designated as an option. Seems a bit inconsistent.
ADD 2
I just tried with below statement in the CMakeLists.txt:
cmake_minimum_required(3.10)
And cmake complains that:
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
cmake_minimum_required called with unknown argument "3.10".
So it seems CMake relies on the VERSION part to properly interpret the "3.10" argument. So I guess the VERSION is also an option here.
And since there's another possible option FATAL_ERROR, it is necessary to have a VERSION option.
So to summarize my current understanding:
The essential paradigm of CMake language is:
CMake commands just manipulate variables based on arguments and options.
Some variables are required to be manipulated and some are optional.
For required ones, their values are specified through arguments. (kind of like positional argument)
For optional ones, their values are specified through argument following corresponding options. (kind of like named argument)
ADD 3
From here, for the VERSION in cmake_minimum_required():
The VERSION is a special keyword for this function. And the value of
the version follows the keyword.
So here it is called keyword instead of option ...
Add 4
Some feelings about CMake...
What is the "VERSION" in "cmake_minimum_required(VERSION 3.10)”
I am just wondering what the VERSION part is syntactically?
A string. VERSION. Nothing special.
Is it a unquoted argument?
Yes.
why do we even need to specify this argument explicitly??
To preserve forward compatibility. The idea is that maybe in the feature there will be cmake_minimum_required(DATE 2021-11-03) or similar, for example.
Is there some kind of string concatenation here?
No. It is set explicitly.
So I can use set_minimum_required(XXX <some_value>) to sent an arbitrary variable with the name CMAKE_MINIMUM_REQUIRED_XXX to <some_value>?
No.
Some variables are required to be manipulated and some are optional.
CMake argument parsing is really crude and simple. It's basically in shell pseudocode if $1 == "VERSION" then check_version($2) else error. How you call those strings is really up to your interpretation that depends on the context, in the context of cmake_minimum_required, sure VERSION is a "keyword". Or a "special required argument". Or similar.
All function arguments are strings, and functions compare them to other strings and execute logic upon that. There are no other variable types. Lists are strings, list elements are separated by ; character in a string.
And the implementation of cmake_minimum_required is here: https://gitlab.kitware.com/cmake/cmake/-/blob/master/Source/cmCMakeMinimumRequired.cxx#L29 . Funny, it looks like the parsing is in a loop, so doing cmake_minimum_required(VERSION VERSION VERSION VERSION 3.11) works as fine.
I think the input to a CMake command can be classified as 3 types:
keyword argument (also called option)
positional argument
variable arguments (like ... in C)
For 1, Like the VERSION in cmake_minimum_required, whose value follows it immediately. It is called keyword or option.
For 2, Such argument has a formal name and is referenced through that name within the command body.
For 3, the argument can be referenced with ARGV, ARGN, ARGVC.
I also see marker argument somewhere. But I forget where. Horrible syntax...
ADD 1
OK I found the marker argument. It's in the book Mastering CMake by the CMake team:
...while the CMake official document says it's an option:
Search the paths specified by the PATHS option or in the short-hand
version of the command. These are typically hard-coded guesses.
What a chaotic wording...
In my project makefile, there is a variable named "--command-variables--". I could guess its meaning from the context, but I want to know more about "--command-variables--". No result from google and GNU make manual.
Here is my test makefile,
all:
$(warning $(-*-command-variables-*-))
#$(warning $(.VARIABLES))
#$(foreach v, $(.VARIABLES), $(info $v===>$($v)))
When I type make test=Makefile, it prints out:
Makefile:2: test=Makefile
make: `all' is up to date.
I found this variables is in .VARIABLES variable, but I can not find it in GNU manual.
The version of make I used is GNU make 3.81.
Can anyone tell me where does this variables defined in or more about these variables? Thank you.
It's one internal variable defined in main.c (line 1344),
/* Define an unchangeable variable with a name that no POSIX.2
makefile could validly use for its own variable. */
(void) define_variable ("-*-command-variables-*-", 23,value, o_automatic, 0);
I have an integer variable that is declared at the head of my subroutine. After I've used it as a control variable inside a forall construct, I can no longer use it as the control variable of a do loop. The compiler (Intel, v. 12.0.3) complains
xyz.f90(1210): error #6404: This name does not have a type, and must have an explicit type. [I]
do i=1,sp_basis%num_dim
---------------^
xyz.f90(1210): error #6063: An INTEGER or REAL data type is required in this context. [I]
do i=1,sp_basis%num_dim
I have tried to write a small example to replicate this behaviour (and compiled the file with the same compiler options as the actual problematic one, apart from -c), but this compiled & worked nicely, so below is my (slightly shortened) problematic code (implicit none applies to the entire module this code belongs to):
subroutine xyz(stuff)
use data, only: ppm, npeaks
! some declarations
integer :: i ! ...
associate(sp_basis => public_spectra%basis(counter))
spots = npeaks * np
allocate(ref_curves(spots,npeaks,sp_basis%num_dim), stat=stat)
if (stat.ne.0) then
! ...
end if
forall (i=1:max_dim) uppers(i) = ubound(sp_int%int,i)
forall (i=1:max_dim) lowers(i) = lbound(sp_int%int,i)
forall (i=1:npeaks,j=1:sp_basis%num_dim) peak_pos_hertz(j,i) = ppm_to_hertz(ppm(permutation(j),i), sp_axes(j))
do peak_considered=1,npeaks
do pos=(peak_considered-1)*np+1,peak_considered*np
do i=1,sp_basis%num_dim ! <-- COMPLAINT
If I change i to a name that was not used as a forall construct's control variable everything works. Also, this is the second time I've run into this problem.
This is how the compilation is done (xyz.f90 is one of many files that make up the entire program):
ifort -c -g -C -check noarg_temp_created -traceback -warn -warn nodeclarations -nogen-interface xyz.f90
Does any of you know what the problem might be?
Thanks a lot for your time!
For all those interested, it's a bug in the Intel compiler. Here you can read more about it. Also it sounds like this bug will be fixed in a compiler version that is to be released some time in 2012.
In summary, is it possible to access via use association a preprocessor directive defined in a Fortran module?
Context
I use preprocessor statements to define subroutines to print warning and error messages. For example, I use the following module/subroutine, in the file errors.f, to print warning messages
module errors
use, intrinsic :: iso_fortran_env, only : error_unit=>stderr
implicit none
contains
!> Print formatted warning message.
subroutine warn_print( file, line, mesg )
implicit none
character(len=*), intent(in) :: file
integer, intent(in) :: line
character(len=*), intent(in) :: mesg
write(stderr,'(a,a,a,i4,a,a)') "WARNING::", file, ":", line, ": ", mesg
end subroutine warn_print
end module errors
and, in a separate file errors.h, I use the above module and define a preprocessor macro
use errors
#define warn( text )warn_print(__FILE__,__LINE__,text)
I then #include the file errors.h in whichever file/module I wish to use the warning print routine which allows me to simply write
call warn("Some warning message")
and the compiler will automatically include the file and line number at which the warning message was called.
Question
The use of #include 'errors.h' is rather idiosyncratic in Fortran code and it hides the use of the errors module. Ideally I would prefer to define the above preprocessor in the errors module itself. However, then when using that module, this preprocessor directive is not available to the program/module which uses this module.
Is there a way to make a preprocessor directive accessible via use association?
The only other way I can think of doing it is to just have the errors module and define the preprocessor directive in my call to the compiler (using, for example, the -D flag with ifort). Any suggestions for any alternative way of achieving the above would be greatly appreciated.
No, it is simply not possible, since the preprocessing and the compilation stages are completely separate one from each other and the C preprocessor does not know anything about the Fortran USE statement.
I use to #include 'config.h' (from autoconf) in most of my .F90 sources, without problems.
This may not be what you are looking for, but if you are using ifort, you can use traceback functionality to achieve something similar (a bit more powerful, but also more ugly), e.g.
program tracetest
call sub(5)
write(*,*) '=== DONE ==='
end program tracetest
subroutine sub(n)
use ifcore
integer :: n
character(len=60) :: str
write(str,*) '=== TROUBLE DETECTED: n =',n ! code -1 means "do not abort"
call tracebackqq(str,-1)
end subroutine sub
Then, compile with -traceback to see the source file, line, and stack trace. The stack trace and line may be obscured because of inlining; to avoid that, you can specify -traceback -O0 to get smth like this:
=== TROUBLE DETECTED: n = 5
Image PC Routine Line Source
a.out 0000000000473D0D Unknown Unknown Unknown
a.out 0000000000472815 Unknown Unknown Unknown
a.out 0000000000423260 Unknown Unknown Unknown
a.out 0000000000404BD6 Unknown Unknown Unknown
a.out 0000000000402C14 sub_ 12 tracetest.f90
a.out 0000000000402B18 MAIN__ 2 tracetest.f90
a.out 0000000000402ADC Unknown Unknown Unknown
libc.so.6 000000323201EC5D Unknown Unknown Unknown
a.out 00000000004029D9 Unknown Unknown Unknown
=== DONE ===
Alternatively, if want to keep the optimizations, and also want to see the correct line (12), you can compile with (for example) -fast -traceback -debug all,inline_debug_info. Something similar may be available in other compilers, but I am not sure.
I want to access some subroutines from a third party DLL. The functions use STDCALL as the calling convention.
Running dumpbin /export foo.dll gives me something like:
...
7 6 00004B40 Foo#16
...
I compile my code using:
gfortran test.f90 -o test.exe -Wl,foo.dll
I get an error: undefined reference to '_foo_' (note the underscores).
I have tried adding the -mrtd compilation flag, as well as other flags I googled, all to no avail.
How can I tell fortran to not add the underscores?
edit: A bit of clarification is in order.
I have an existing DLL to which I do not have the source to.
This DLL is written in Visual Basic, if it helps.
I want to call this DLL from fortran.
When I write in test.f90: Foo(1.0d0) I get an undefined reference to '_foo_' linkage error
Did you try -fno-underscoring ?
I found a post by Tobias Burnus (a gfortran developer) at http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html (near the end) -- he recommends the use of compiler directives instead of -mrtd.
You need to combine the use of ISO_C_BINDING with compiler attributes. You should really read the Mixed-Language Programming section of the gfortran manual. It gives good advice that can be used with other compilers as well. In particular, in your case you need the stdcall attribute:
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
!GCC$ ATTRIBUTES stdcall :: foo
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs
Notice the line with stdcall, it's what should make it work.
Just wanted to expand on M.S.B's -fno-underscoring answer: You may run into issues if using f2c & g77. From the gfortran documentation:
With -funderscoring in effect, GNU
Fortran appends one underscore to
external names with no underscores.
This is done to ensure compatibility
with code produced by many UNIX
Fortran compilers.
Caution: The default behavior of GNU
Fortran is incompatible with f2c and
g77, please use the -ff2c option if
you want object files compiled with
GNU Fortran to be compatible with
object code created with these tools.
Use of -fno-underscoring is not
recommended unless you are
experimenting with issues such as
integration of GNU Fortran into
existing system environments
(vis-à-vis existing libraries, tools,
and so on).
You might need to recompile the DLL with something like -fno-underscoring to remove the underscores from the DLL.
I've run into portability issues related to underscore prefix/suffix by certain Fortran compilers: Some compilers _prefix or suffix_ by default, while others don't! My solution has been preprocessor directives:
#ifdef LC_UNSC
#define GET_DIP_MOMENT get_dip_moment_
#elif LC_NOUNSC
#define GET_DIP_MOMENT get_dip_moment
#endif
...
call GET_DIP_MOMENT()
A different approach is to use the ISO C Binding of Fortran 2003, which is supported by gfortran >= 4.3. This will automatically use the underscoring conventions of C (i.e., probably none), rather those of the Fortran compiler. It will also give you control over the case (capitalization) of the subroutine names, if the Windows linker cares about that. Fortran is case insensitive, and so you can call Fortran subroutines by any case -- probably the linker is converting to lower case.
Including the following "interface" in the declarations of the Fortran routine that calls "Foo" describes Foo to be a C subroutine (void function) with a single argument of double type -- Fortran input/output, or a pointer in C. If Foo has other properties, the interface needs to be changed. The "bind" clause specifies the case-sensitive name to provide to the linker. If you call Foo from several Fortran routines, then it is best to put the interface into a module and "use" it from each Fortran routine.
This is intended for C -- maybe it will work for Visual Basic. The ISO C Binding gives a lot of control, so if this doesn't work, maybe some variation will.
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs