Compile dodgy Fortran 77 code in a modern compiler - linux

I am trying to compile a piece of software written in Fortran 77. I should point out that I don't know much at all about Fortran, and would really rather not start modifying the code for this software - particularly as I'm not sure what the licensing of the software is, and I don't know if I would be able to redistribute my modified version.
The code compiles fine on OS X and Windows using the g77 compiler that is (fairly easily) available for these systems. However, I cannot get it to work on my Ubuntu distribution, as I can't seem to get hold of g77 for Ubuntu anymore, and if I try and install an old version of it, it seems to muck up my entire GCC installation. I have tried compiling the code with both gfortran and g95, but it doesn't work with either as:
The code uses real variables as loop indices (yes, I know, bad idea). g95 supports this with the -freal-loops option, but gfortran doesn't.
The code uses real variables to index into arrays, which gfortran will support (with a warning), but g95 won't support.
Can anyone suggest a way to compile this code with those two 'dodgy' features using a modern and easily-available compiler such as g95 or gfortran?

Pass the argument -std=legacy to gfortran. Features removed in F95, like real loop and array indices, should compile (perhaps with a warning) in legacy mode.

Related

How to use assembly code you get online?

I have some C code I would like to optimize. It turns out the Intel C Compiler (ICC) does a much better job at this than GCC but I don't have a copy of that compiler and it is very expensive. However, I can compile it using ICC and get the assembly online at godbolt.org.
If I copy and paste this assembly into a text file, how can I then convert it into a functioning executable?
You will need to begin by making sure that the runtime environment for which godbolt.org compiles is similar enough to your runtime environment, (good luck with that,) because for example you may be using windows, and godbolt.org may be using linux, (or the other way around,) so when you bring the assembly to your system you might be able to convert it to object code, but it will still not link and it will not run.
Then you will need to find an assembler for your platform which is compatible with the syntax of assembly produced by the intel C compiler of godbolt.org so as to produce object files from the assembly files. (Good luck with that.)
Then you will need to find any and all runtime libraries (redistributables) required by code produced by the intel C compiler. (Good luck with that.)
Finally you will need to obtain a linker to link your resulting object files with the runtime libraries to produce an executable. (Good luck with that.)
Sometimes we need honest answers to our questions just so that we can realize how impossible our ideas are.

Compile linux gcc in windows - nvcc in windows

here is an interesting question that, if answered positively, would make cross compiling a whole lot easier.
Since gcc is written in C++, would it be possible to recompile the Linux gcc compiler on Windows MinGW G++ or VSC++ compiler, so that the resulting Windows executable would be able to compile c code to linux programs?
If so, what would be needed to do that?
So to simplify, here is what I want to do.
mingw32-g++ gcc.cpp -o gcc.exe
The command will probably not work because it would probably have been done before if it were that easy. What I ask is if this concept would be even possible.
Edit: thanks and expanding the question to NVCC
fvu was able to answer the question for the gcc compiler (please use the answer button next time), so if you had the same question you can thank him (or her) .
As an extention to the question, would it be possible to edit or recompile nvcc or the things it uses so that nvcc.exe can create a linux program from CUDA C code? I read that the windows variant of nvcc can only use the Visual Studio cl.exe and not MinGW or CygWin.
Is it possible to create linux programs with cl.exe? And if so, could that be used to generate linux programs with nvcc.exe?
Read the chapter on cross compiling in the gcc manual, gcc's architecture makes it quite easy to set up a toolchain where the target is different from the development machine.
I never went the exact route you describe, but I have built toolchains under Windows that target ARM9 embedded Linux machines, works like a charm - using cygwin btw. Look here for a gentle introduction. Also very useful info here.
I am not going to comment on what can be done with respect to nvcc, CUDA is somewhere on my (long) list of stuff to tinker with...
Now, can cl generate Linux binaries? The answer to this question is "sort of" : as long as the target processor is from a processor family that's supported by cl, the object files generated by it should probably not contain anything that would inhibit its execution on Linux, as they'll just contain machine code. That's the theory. However:
as Linux uses another executable format, you will need a Windows-hosted linker that understands Windows style object files (afaik, COFF), and links them together to a Linux style (ELF) executable. I never heard of such a beast, although in theory it could exist
the startup code (a tiny program that wraps around your main function) will also be different and needs to be written
and some more, eg library related issues
So, the practical answer is no, although it might be a nice summer project for a bored student :)

Can Clang compile code with GCC compiled .a libs?

I have my project currently compiling under gcc. It uses Boost, ZeroMQ as static .a libraries and some .so libraries like SDL. I want to go clang all the way but not right now. I wonder if it is possible to compile code that uses .a and .so libraries that were compiled under gcc with clang?
Yes, you usually can use clang with GCC compiled libraries (and vice versa, use gcc with CLANG compiled libraries), because in fact it is not compilation but linking which is relevant. You might be unlucky and get unpleasant suprises.
You could in principle have some dependencies on the version of libstdc++ used to link the relevant libraries (if they are coded in C++). Actually, that usually does not matter much.
In C++, name mangling might in theory be an issue (there might be some corner cases, even incompatibilities between two different versions of g++). Again, in practice it is usually not an issue.
So usually you can mix CLANG (even different but close versions of it) with GCC but you may have unpleasant surprises. What should be expected from any C++ compiler (be it CLANG or GCC) is just to be able to compile and link an entire software (and all libraries) together using the same compiler and version (and that includes the same C++ standard library implementation). This is why upgrading a compiler in a distribution is a lot of work: the distribution makers have to ensure that all the packages compile well (and they do get surprises!).
Beware that the version of libstdc++ does matter. Both Clang & GCC communities work hard to make its ABI compatible for compiler upgrades, but there are subtle corner cases. Read the documentation of your particular and specific C++ standard library implementation. These corner cases could explain mysterious crashes when using a good C++ library binary (compiled with GCC 5) in your code compiled with GCC 8. The bug is not in the library, but the ABI evolved incompatibly.
At least for Crypto++ library this does not work (verified :-( ). So for c++ code it is less likely to work, while pure c code would probably link OK.
EDIT: The problem started appearing with Mac OS X 10.9 Mavericks and Xcode-5, which switched the default C++ library for clang from libstdc++ to libc++. It did not exist on Mac OS X 10.8 and earlier.
The solution appears to be: if you need to compile C++ code with clang, and link it to a gcc-compiled library, use "clang++ -stdlib=libstdc++". The linking is successful, and the resulting binary runs correctly.
CAVEAT: It does not seem to work the other way: even though you can build a library compiled with "clang++ -stdlib=libstdc++" and link gcc-compiled code with it, this code will crash with SEGV. So far I found the only way to link with a clang-compiled library is compiling your code with clang, not gcc.
EDIT2:
GCC-12 seems to include -stdlib= flag. Compiling with g++ -stdlib=libc++ creates Clang++-compatible object files. Very nice.
I do have an additional data point to contribute, on the topic of "unpleasant surprises" mixing code from different versions of different compilers. Therein, I link Victor Shoup's C++-based NTL number theory library with a small piece of driver code that just prints out a large factorial computed by the NTL code, a number with a decimal representation that might span multiple lines if sufficiently large.
I have built and installed SageMath (and its version of NTL) on my system running OS X 10.11.6, and also have a current installation of MacPorts. In /usr/bin I find for gcc --version
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
My MacPorts gcc gives
gcc (MacPorts gcc9 9.1.0_2) 9.1.0
Now, the SageMath build system requires that MacPorts be moved out of the way, so I assume SageMath builds NTL using Apple's development toolset. The SageMath build log is full of invocations of gcc. SageMath actually builds gcc from source if the system on which the makefile is run has too old a version of Apple's developer tools.
My driver code computes big factorials and uses methods of the NTL class ZZ; I initially had tested this by linking to an NTL static library I built myself, and I changed it to link to the SageMath version because I find it pleasing not to duplicate libraries. Now I understand a bit more about the pitfalls which may arise in this process.
The old makefile invoked g++ to make the executable, but this failed at linking phase with the message:
Undefined symbols for architecture x86_64:
"NTL::operator<<(std::basic_ostream<char, std::char_traits<char> >&, NTL::ZZ const&)",
referenced from:
prn_factorial(int, NTL::ZZ&) in print.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
I had to think about this and run experiments for about 15 minutes before deciding on my own to change the makefile to invoke clang++ which in my current path invokes the MacPorts version
clang version 7.0.1 (tags/RELEASE_701/final)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-7.0/bin
This time, the makefile successfully linked and built my executable. I conclude that this represents one of those edge cases with "unpleasant surprises". Probably I should conclude that working with details of C++ is not for me; big software systems like SageMath are developed just so hobbyists don't really have to muck around with details like these.

GCC/G++: building without GNU unique object symbols for older Linux kernels

I am currently working on updating the build system for a large pile of code, which happens to include a Linux C++ project. It would be nice if all of the developers here could run a build when hacking around with their own ideas, so I was examining if it would be possible to build this on vaguely modern Linux systems despite the target system being 2.6.18.
By 'vaguely modern' I am estimating something like GCC 4.5+, something that a distribution in the past year or two might come with. Currently I solve the libstdc++ issue by compiling that in statically, and any glibc issues are neatly worked around by remapping to old versions of the memcpy symbols (and so on) with a quick bit of wrapper code. So far so good.
The one problem I can't seem to completely figure out is that certain symbols built into the executable from the .o files are of type 'u', which is a GNU unique object, an extension to the ELF standard that 2.6.18 doesn't seem to recognise at all. This means the executable won't run because it can't find the symbols, though they are in fact present (just of type '?' on the target, from 'nm').
One can disable the use of GNU unique objects when compiling G++ but it's not exactly the most convenient solution. I can't see any way to just disable it when compiling code (distro gcc/g++ invariably has this option on), and I imagine the only way to get the target system to recognise it would be to update ld-linux and the kernel. That's almost certainly not going to happen.
Is there an option I haven't found to disable these symbol types? Or perhaps is there some neat way around this, or something that I'm missing? I am beginning to suspect it will just have to be compiled on G++ 4.1.x, which will mean an old Linux installation or building that from source.
I was trying to deal with the same problem (which led me to finding this question) and after a bunch of research came to the definitive conclusion that no, you are not missing anything, there is no way around this besides compiling your own g++. See this recent question on the gcc-help mailing list:
http://gcc.gnu.org/ml/gcc-help/2013-01/msg00008.html
I compared gcc sources and found that you can go as high as stock 4.4, as unique symbols were added in 4.5. However on RHEL/CentOS 6 they default to 4.4 but patched unique symbol support into it, so as usual one must beware of distribution-specific gcc versions. For me this is a huge bummer as it means that things compiled on RHEL 6 can't be run on RHEL 5, even with a copy of libstdc++ made just for gcc 4.4 + RHEL 5.
Here's the message where unique symbol support was first proposed, by the way:
https://gcc.gnu.org/ml/gcc-patches/2009-07/msg01240.html
If you search around you'll find that people have complained about it on other lists for various reasons, but I guess it's here to stay.

Is it possible to compile Linux kernel with something other than gcc

I wonder if someone managed to compile the Linux kernel with some other compiler than gcc. Or if someone have ever tried? Question may seem to be silly or academic, but it arose when I thought about answers to: Are C++ int operations atomic on the mips architecture
It seems that the atomicity of some operations depends not only on the cpu architecture, but also on used compiler. So, I wonder if in Linux world some compiler other than gcc even exists.
Linux explicitly depends on some gcc extensions, so any other compiler must be compatible with the needed extensions, in that case.
This is not a "no", since it's of course not impossible for a separate compiler vendor/developer to track gcc's extensions, just a data point that might help you search.
At some point tcc would process and run the linux kernel source. SO that would be a yes, I guess.
::Hat tip to ephemient in the comments.::
The LLVM developers are trying to compile it with clang. The meta-bug on compiling the Linux kernel with clang has more details (the dependency tree for that meta-bug shows how little seems to be left).
There have been some efforts (and patches) to compile an early version of the 2.6 kernel with icc.
Yup. I've done this. See [cfe-dev] Clang builds a working Linux Kernel (Boots to RL5 with SMP, networking and X, self hosts).
IBM's compiler was able to do it some Linux versions ago, but I'm not sure about now, nor am I sure of how well IBM optimized the kernel as instructed. All I know is, they got it to build.
As Linux is self hosting (with its own libc) and has been developed from the start with gcc (and gcc cross compilers), its sort of silly to use anything else.
I think mainly, playing nice with preprocessor macros and instructed optimizations is the biggest obstacle (not even getting into a departure from gas), as GNU has basically written the book on the above, and extended it. Beyond that, Linux tunes its optimizations to work with gcc, for instance, don't get caught using 'volatile' in the kernel without a damn good reason. Using inline and actually having the compiler agree is another challenge.
Linus is the first one to call GCC an &*#$ hole, which makes for a better compiler.
This is why we have the great GNU/Linux debate.
Many, many, many years ago, it was actually possible to compile the kernel with g++, and as far as I remember part of the motivation was because C++ had stronger type check, not necessarily to have g++ to produce object files. But as Neil Butterworth have pointed out, Linus is not particular fond of C++, and there is zero chance that this ever will be possible again.
EKOPath 4 Compiler, not now. but probably with some minor patches
https://github.com/path64/repositories
http://www.pathscale.com/ekopath-compiler-suite
I am just now working on compile Linux kernel using Open64 for MIPS archtecture, and some other guys are now just working for make Open64 can build for X86 arch. Now the kernel can partly run, and still have Run fail errors.
However for the atomic problem, at least i have not come up with it. And I do not think it is really a problem.The reasons are:
The Linux kernel have already been a collection of source code, which can successfully build with GCC, so it is only the compiler's problem if it can not build it, or the built kernel runs fail.
If a compiler want to successfully build Linux kernel, it should obide the GNU C Extension, and this extension will give a clear discription of what a atomic operation is, so such a compile only need to generate code according to this extension.
My non-technical guess: The Linux Kernel can't currently (2009) be compiled with any compiler other than the GNU compiler, gcc.
I say this on the basis that I've heard Richard Stallman, with some conviction, say Linux should be called GNU/Linux because the kernel is "only 1 part of the operating system" and I'm guessing he would not be able to say this if the kernel was non-dependant on GNU (e.g. a tonne of embedded devices run a Linux OS without any GNU software).
As I said, just a guess, let me know if I'm wrong...

Resources