I'm recently reading Microsoft RPC Programming, here I have a question about the makefile in chapter 1, here is the portion of the makefile:
# FILE NAME: Makefile
# Makefile for the arithmetic application
##
definitions for this makefile
#
APPL=arith
NTRPCLIBS=rpcrt4 . lib rpcns4.1ib libcmt.lib keme!32.1ib
# Include Windows NT macros
#
!include <ntwin32.mak>
what I can't understand is the last line, why there is a !? I've check the ntwin32.mak, here is its content:
!include <win32.mak>
Then what's the meaning of this, why !include <win32.mak>? Why not just include <win32.mak>?
what I can't understand is the last line, why there is a !? [...] why !include <win32.mak>? Why not just include <win32.mak>?
Since you found that (pseudo-)makefile in a book about programming for Microsoft platforms, it is presumably intended for nmake, Microsoft's variation on make. This implementation has a lot in common with traditional Unix-style make, but also some significant differences. Among the latter is a series of "preprocessing directives", which are recognized by the fact that they each begin with an exclamation point (!). !include is among these.
The preprocessing directives seem to have been modeled more on the C preprocessor than on traditional make, which you may also recognize in the support for angle brackets around the name of the file to be !included. At the same time, nmake uses the same symbol as standard make to mark comments (#), so that is not available to make their directives match C's exactly. They've chosen the exclamation point as a substitute.
Overall, although Microsoft still distributes and supports nmake, it has long focused on Visual Studio instead as the platform for building software for Windows. You're probably better off developing expertise with that tool than learning the peculiarities of nmake.
Related
I'm trying to locate where __builtin_va_start is defined in GCC's source code, and see how it is implemented. (I was looking for where va_start is defined and then found that this macro is defined as __builtin_va_start.) I used cscope -r in GCC 9.1's source code directory to search the definition but haven't found it. Can anyone point where this function is defined?
That __builtin_va_start is not defined anywhere. It is a GCC compiler builtin (a bit like sizeof is a compile-time operator). It is an implementation detail related to the <stdarg.h> standard header (provided by the compiler, not the C standard library implementation libc). What really matters are the calling conventions and ABI followed by the generated assembler.
GCC has special code to deal with compiler builtins. And that code is not defining the builtin, but implementing its ad-hoc behavior inside the compiler. And __builtin_va_start is expanded into some compiler-specific internal representation of your compiled C/C++ code, specific to GCC (some GIMPLE perhaps)
From a comment of yours, I would infer that you are interested in implementation details. But that should be in your question
If you study GCC 9.1 source code, look inside some of gcc-9.1.0/gcc/builtins.c (the expand_builtin_va_start function there), and for other builtins inside gcc-9.1.0/gcc/c-family/c-cppbuiltin.c, gcc-9.1.0/gcc/cppbuiltin.c, gcc-9.1.0/gcc/jit/jit-builtins.c
You could write your own GCC plugin (in 2Q2019, for GCC 9, and the C++ code of your plugin might have to change for the future GCC 10) to add your own GCC builtins. BTW, you might even overload the behavior of the existing __builtin_va_start by your own specific code, and/or you might have -at least for research purposes- your own stdarg.h header with #define va_start(v,l) __my_builtin_va_start(v,l) and have your GCC plugin understand your __my_builtin_va_start plugin-specific builtin. Be however aware of the GCC runtime library exception and read its rationale: I am not a lawyer, but I tend to believe that you should (and that legal document requires you to) publish your GCC plugin with some open source license.
You first need to read a textbook on compilers, such as the Dragon book, to understand that an optimizing compiler is mostly transforming internal representations of your compiled code.
You further need to spend months in studying the many internal representations of GCC. Remember, GCC is a very complex program (of about ten millions lines of code). Don't expect to understand it with only a few days of work. Look inside the GCC resource center website.
My dead GCC MELT project had references and slides explaining more of GCC (the design philosophy and architecture of GCC changes slowly; so the concepts are still relevant, even if individual details changed). It took me almost ten years full time to partly understand some of the middle-end layers of GCC. I cannot transmit that knowledge in a StackOverflow answer.
My draft Bismon report (work in progress, funded by H2020, so lot of bureaucracy) has a dozen of pages (in its sections ยง1.3 and 1.4) introducing the internal representations of GCC.
I would like to know the Uses of static pattern rules against normal rules in make. I an new to make and gone through some tutorials. I want to know when do we use this static pattern rules ? Could you please explain in brief ?
Thanks in Advance.
Your question is mostly a matter of opinion. Notice that there are several build automation tools (not only GNU make), e.g. also ninja, scons, omake, etc...
When you code in C (or in C++....) some project, you could have some C (or C++) files which are generated from something else (e.g. by lemon or by your own utility...). For such cases (pedantically you could call them metaprogramming), pattern rules could be useful (in particular if you have several such cases in a project). In other cases you generate other files (than object files) from C source (e.g. generating documentation with doxygen), and then pattern rules are also very useful.
An example of a large C++ project with many C++ code generators is the GCC compiler. And back when (in 2009) GCC was coded in C, it already had a dozen of specialized code generator programs emitting some C code. For these cases, pattern rules could be convenient.
Of course, pattern rules are a luxury. You could in principle generate your Makefile and have it contain a simple rule for each individual file. (in GCC, the Makefile-s are generated by autoconf and automake based things...)
If you observe and study the source code of most large free software projects, you'll find out that most of them do have generators for C (or C++) files. So generating C code is a usual practice (the original Unix from late 1970s did that already). Today, some software projects have most or even all (e.g. CAIA) of their C code generated.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am working on a custom CFD Solver written in Fortran 90 and MPI.
The code contain 15+ Modules and was initially designed to work with the Intel Fortran compiler. Now since i do not have access to the Intel compiler I need to make it work using the GNU Fortran Compiler.
I made changes in the Makefile that initially had flags suitable for the ifort.
I am using it on Ubuntu with GNU Fortran and Openmpi
I am sorry I am unable to put in anything from the code structure or terminal output due to IP restrictions of my university. Nevertheless,I will try to best describe the issues
So now when I compile the code I am having some strange issues.
The GNU Fortran is not able to read lines that are too long and I get errors during compilation. As a result I have to break it into multiple lines using the '&' symbol
A module D.f90 contains all the Global variables declared. However, now I during compilation i get error is in module B.F90.
The error I get is 'Unclassified Statement Error', I was able to fix it in some subroutines and functions by locally declaring the variables again.
I am not the most experienced person in Fortran, but I thought that the change in compiler should not be a reason for new found syntax errors.
The errors described above so far could be remedied but considering the expanse of the code it is impractical.
I was hoping if anyone could share views on this matter and provide guidance on how to tackle it.
You should start reading three pieces of documentation:
The Fortran 90 standard (alternatively, other versions), which tells you what is legal, standard Fortran and what is not. Whenever you find some error, look at your code and check if what you are doing is legal, standard Fortran. Likely, the code in question will either be completely nonstandard (e.g. REAL*8, although that extension is fairly well understood) or rely on unspecified behaviour that Intel Fortran and GFortran are interpreting in different ways.
The GFortran manual for your version, which tells you how GFortran decides such unspecified cases, what intrinsic functions are available, how to change some options/flags, etc. This would tell you that your problem with the line lengths would be solved by adding -ffree-line-length-none.
The Intel Fortran manual for your version, which in cases of non-standard or unspecified behaviour, will allow you to know what the code you are reading was written to do, e.g. the behaviour that you would expect. In particular, it will allow you to decipher what the compiler flags that are currently being used mean. They may or may not need translation to GFortran, e.g. /Qsave will need to become -f-no-automatic.
A concrete example of interpretative differences within the range allowed be the standard: until Fortran 2003, the units for the "record length" in random access record files were left unspecified. Intel Fortran used "one machine word" (4 bytes in x86) while GFortran used 1 byte. Both were compliant with the standard letter, but incompatible.
Furthermore, even when coding "to standard", you may hit a wall if the compiler does not implement part of the Fnn standard, or it is buggy. Case in point: Intel Fortran 12.0 (old, but it's what I work with) does not the implement the ALLOCATE(y, SOURCE=x) construct for polymorphic x (the "clone allocation"). On the other hand, GFortran has not completely implemented FINAL type-bound procedures (destructors).
In both cases, you will need to find workarounds. For example, for the first issue you can use a special form of the INQUIRE statement (kudos to #haraldkl). In other cases, the workaround might even involve using some kind of feature detection (see autoconf, CMake, etc.) and storing the results as PARAMETER variables in a config.f90 file that is included by your code. Your code would then take decisions based on it, as in:
! config.f90.in (things in #x# would get subtituted by automake, for example)
INTEGER, PARAMETER :: RECORD_LEN_BYTES = #RECORD_LEN_BYTES#
! Some other file which opens a file
INCLUDE "config.f90"
!...
OPEN(u, FILE='DE430.BIN', ACCESS='direct', FORM='unformatted', RECL=56 / RECORD_LEN_BYTES)
People have been having complaints about following the standard since at least the 60s. But those cDEC$ features were put in a for good reasons...
It is valuable to cross compile though and you usually have things caught in one compiler or the other.
For you question #1 "The GNU Fortran is not able to read lines that are too long and I get errors during compilation. As a result I have to break it into multiple lines using the '&' symbol"
In the days of old there was:
options/extended_source
SUBROUTINE...
In fort it is -132, but I have not found a gfortran equivalent to -132 . It may be -ffixed-line-length-n -ffixed-line-length-none -ffree-line-length-n -ffree-line-length-none per the link: http://www.math.uni-leipzig.de/~hellmund/Vorlesung/gfortran.html#SEC8
Also the ifort standard for .f90 and .f95 is the the compiler switch '-free' '-fixed' is the standard <.f90... However one can use -fixed with .f90 and use column 6 and 'D' in column #1... Which is handy with '-D_lines' or '-DD'.
Per the link: https://software.intel.com/sites/default/files/m/f/8/5/8/0/6366-ifort.txt
For you question #2: "A module D.f90 contains all the Global variables declared. However, now I during compilation i get error is in module B.F90. The error I get is 'Unclassified Statement Error', I was able to fix it in some subroutines and functions by locally declaring the variables again."
You probably need to put in the offending line, if you can get an IP waiver.
Making variables local if they are expected to be shared in a /common/ or shared in a module will not work.
If there were in /common/ or PUBLIC then they are shared.
If they are local then they are PRIVATE.
it would be easy to get that error if a PRIVATE statement was in the wrong place, or a USE statement was omitted.
I am currently working on cleaning up a huge legacy program written in Fortran and preprocessed with '-traditional'.
I am aware that this seems to be the common way to do it. However the code is peppered with lots and lots of pp symbols ('#define', '#ifdef' and such) which completely break the indentation and make it very hard to read and understand 10s of thousands of lines of code written by multiple other authors over decades. Since my main task is to enhance the readability and maintainability of the code, I'd love to indent those while cleaning up. Sadly, this seems to be impossible with '-traditional'.
Afaik the main reason for using '-traditional' with Fortran is comment handling. the Fortran concatenation symbol '//' is a line comment in c and is therefore removed by cpp, thus breaking the code. I'm aware of the -c or -cc options but since this program is using some external libraries with c-style block comments ('/* */') this won't work either. There's also c-style block comments within the source, which i could replace with line comments, but I can't change the style of comment in the external libraries.
Is there any way to make Fortran code with c-style block comments work without '-traditional'?
Or alternatively: is there any way to make indentation of pp symbols work with '-traditional'?
edit:
The code is usually compiled with gfortran. But compatibility with Solaris Studio is required too.
I see that Fortran has 'call' and 'include' statements. what is the difference between the two? Does the .i filetype have some significance?
i.e:
include 'somefile.i'
call 'somesubroutine.f'
Thanks!
INCLUDE statement lets you include source from some other file, as if it was in the file in which the statement is located. Its usefulness in organizing code is somewhat dubious, but some swear by it.
In F77 it was a common extension (from MIL-STD 1971, I believe), in F90 it made it into the Standard.
Filetypes have no significance. As the matter of fact, in fortran most filetypes (even the more common ones as f77, f90 and such) have no significance. Most compilers merely use them to automatically "detect" and differentiate free form from fixed form source code, but they also allow for other.
CALL statement is used for calling subroutines. It is of the form CALL subroutine_name(list-of-arguments). Subroutines are one of the more simple ways of structuring and dividing your program into logical sub-units.
But this is all relatively basic, and covered in every Fortran tutorial out there. Some are better, some are worse. A few good starting points for learners would be the Wikipedia page (not perfect, but not that bad either), FortranWiki and two books. One IRO-bot already mentioned, other would be Chapman's Fortran 95/2003 for scientists and engineers. It is generally considered more suitable for beginners, having an easy going approach and a plethora of practical examples, while Metcalf is aiming to be more of a reference book as well.
In general, file extensions don't have special meaning for the compiler. You can include any file, not just .i. Common extension for Fortran source files is .inc though.
include statement literally inserts a specified file into the source code.
call statement is very different, and it is used to call a Fortran subroutine.
These are very basic concepts. Before all, you should look up an introductory Fortran tutorial online (just try googleing it). Or get one of several great books on Fortran programming, e.g. Metcalf and Reid.