linking multiple files with fortran - file

I'm new to Fortran but I'm trying to find a way that I can retrieve information from programs I've written without including them as subprograms within my new file. As of right now I have 4 subroutines within my new file and I would like to instead just be able to input the radius into all 4 and receive their respective outputs.
this is the basic format for my code--- basically I want to show that I need 4 separate programs in order to get all the variables needed for the current programs expression.
So far I've tried to use both the include and call expressions but they weren't able to retrieve the information I needed to bring back into my file and they came up with just "not applicable" answers.
program practicedynamo
implicit none
real:: A,B,C, Radius
real::Bsquared,Vsquared
read*,radius
call programA(radius,A)
call programB(radius,B)
call programC(radius,C)
Vsquared=(1.0/3.0)*B
Bsquared= 4*pi*density*Vsquared
gradient=radius*C
Rvector=Bsquared*Vsquared*gradient
ThetaVector=Rvector*sin(A)
end program practicedynamo
!and then my four subroutines would be placed afterwards
!here is an example of one of my subroutines within my actual code (the version above has been simplified and I've changed the variables)
subroutine testdensity(radius,density)
implicit none
real::radius,x,sunradius,density
if (radius>0.and.radius<=695500000) then
sunradius=695500000
x=radius/sunradius
density=((519*x**4.0)-(1630*x**3.0)+(1844*x*x)-(889*x)+155)
print*," "
density=density*1000
print*,"the density is",density, "kg per meters cubed"
else
print*, "this radius is not an option for the sun"
end if
end subroutine testdensity

You haven't mentioned how you are compiling your code, but here are some general ways to include multiple source files in a single executable. You don't need to include the files, you can just compile them separately and link them together. Writing a Makefile to do this is recommended and you can find plenty of examples on that elsewhere.
To compile multiple files into one executable, you need only list them all when compiling
gfortran -o output programA.f90 programB.f90 programC.90 mainprogram.f90
If you do not want to compile them all together or have to recompile when you build, you can compile individual objects, e.g.
gfortran -c -o programA.o programA.f90
gfortran -c -o programB.o programB.f90
gfortran -c -o programC.o programC.f90
and then link as
gfortran -o output mainprogram.f90 programA.o programB.o programC.o
If you are instead trying to use libraries and want program A-C to be in a standalone library, you can first compile the objects as above, then
ar rcs libABC.a programA.o programB.o programC.o
and then compile your main program as
gfortran -o output mainprogram.f90 libABC.a
If you aren't using modules, you'll be responsible for making sure that your calls to external subroutines match the declared interface in the external file. To be safe and have the compiler catch problems with mismatched arguments you can declare explicit interfaces in your program or put the external code into modules and use those modules in the main program.

Related

Compile and Link to .com file with Turbo C

I'm trying to compile and link a simple program to a DOS .com file using Turbo C compiler and linker. By that I try the simplest C-program I can think of.
void main()
{}
Are there command line arguments to link to com files in the Turbo C Linker?
The Error Message I get from the Linker is the following:
"Fatal: Cannot generate COM file: invalid entry point address"
I know that com files need entry point to be at 100h. Does Turbo C have an option to set this address?
It has been a long time since I have genuinely tried to use Turbo-C for this kind of thing. If you are compiling and linking on the command line separately with TCC.EXE and TLINK.EXE then this may work for you.
To compile and link to a COM file you can do this for each one of your C source files creating an OBJ file for each:
tcc -IF:\TURBOC3\INCLUDE -c -mt file1.c
tcc -IF:\TURBOC3\INCLUDE -c -mt file2.c
tcc -IF:\TURBOC3\INCLUDE -c -mt file3.c
tlink -t -LF:\TURBOC3\LIB c0t.obj file1.obj file2.obj file3.obj,myprog.com,myprog.map,cs.lib
Each C file is compiled individually using -mt (tiny memory model) to a corresponding OBJ file. The -I option specifies the path of the INCLUDE directory in your environment (change accordingly). The -c option tell TCC to compile to a OBJ file only.
When linking -t tells the linker to generate a COM program (and not an EXE), -LF:\TURBOC3\LIB is the path to the library directory in your environment (change accordingly). C0T.OBJ is the C runtime file for the tiny memory model. This includes the main entry point that you are missing. You then list all the other OBJ files separated by a space. After the first comma is the output file name. If using -t option name the program with a COM extension. After the second comma is the MAP file name (you can leave the file name blank if you don't want a MAP file). After the third comma is the list of libraries separated by spaces. With the tiny model you want to use the small model libraries. The C library for the small memory model is called CS.LIB .
As an example if we have a single source file called TEST.C that looks like:
#include<stdio.h>
int main()
{
printf("Hello, world!\n");
return 0;
}
If we want to compile and link this the commands would be:
tcc -IF:\TURBOC3\INCLUDE -c -mt test.c
tlink -t -LF:\TURBOC3\LIB c0t.obj test.obj,test.com,test.map,cs.lib
You will have to use the paths for your own environment. These commands should produce a program called TEST.COM. When run it should print:
Hello, world!
You can generate COM file while still using IDE to generate EXE. Following worked on TC 2.01. Change memory model to Tiny in the options, then compile the program and generate EXE file, then go to command prompt, and run EXE2BIN PROG.EXE PROG.COM. Replace PROG with your program name.
Your problem is about "entry point"
some compiler or linker can recognize void main() like entry point omiting a return value but no all of them.
You shoud use int main() entry point instead for better control of app and compiler can recognize main function as entry point
example:
int main() {
/* some compiler return 0 when you don't for main,
they can ask for return value */
}
from geekforgeeks:
A conforming implementation may provide more versions of main(), but they must all have return type int. The int returned by main() is a way for a program to return a value to “the system” that invokes it. On systems that doesn’t provide such a facility the return value is ignored, but that doesn’t make “void main()” legal C++ or legal C. Even if your compiler accepts “void main()” avoid it, or risk being considered ignorant by C and C++ programmers.
In C++, main() need not contain an explicit return statement. In that case, the value returned is 0, meaning successful execution.
source: https://www.geeksforgeeks.org/fine-write-void-main-cc/

How can compiling the same source code generate different object files?

After a long sequence of debugging I've narrowed my problem down to one file. And the problem is that the file compiles differently in two different directories, when everything else is the same.
I'm using CodeSourcery's arm gcc compiler (gcc version 4.3.3, Sourcery G++ Lite 2009q1-161) to compile a simple file. I was using it in one module with no issues and then I copied it to another module to use there. When it compiles, the object file is significantly different. The command line to compile the two files is identical (I used the linux history to make sure), and the 3 include files are also identical copies (checked with diff).
I did a binary compare on the two object files and they have a lot of individual byte differences scattered around. I did an objdump -D of both and compared them and there are a lot of differences. Here is dump1, dump2, and the diff. The command line is "
arm-none-eabi-gcc --std=gnu99 -Wall -O3 -g3 -ggdb -Wextra -Wno-unused -c crc.c -o crc.o".
How is this possible? I've also compiled with -S instead of -c and looked at the assembler output and that's identical except for the directory path. So how can the object file be different?
My real problem is that when I try to link the object file for dump2 into my program, I get undefined reference errors, so something in the object is wrong, whereas the object for dump1 gets no such errors and links fine.
For large scale software, there are many implementations are doing hashing on pointers. This is one major reason that cause result randomization. Usually if the program logic is correct, the order of some internal data structures could be different which is not harmful in most cases.
And also, don't compare the 'objdump -D' output, since your are compiling the code from different directory, the string table, symbol table, DWARF or eh_frame should be different. You will certainly get lots of diff lines.
The only comparison that makes sense is to compare the output of 'objdump -d' which only takes care of the text section. If text section is same(similar) then it can be considered as identical.
Most likely your file picks up different include files. This this the most likely reason.
Check that your include paths are exactly the same, paths in the include statements. They may point to different directories. C and C++ has a feature that when you #include abcd.h it tries to load abcd.h from the directory of the calling file. Check this.

Statically linking libclang in C code

I'm trying to write a simple syntax checker for C code using the frontend available in libclang. Due to deployment concerns, I need to be able to statically link all the libraries in libclang, and not pass around the .so file that has all the libraries.
I'm building clang/llvm from source, and in llvm/Release+Asserts/lib I have a bunch of .a files that I think I should be able to use, but it never seems to work (the linker spews out thousands of errors about missing symbols). However, when I compile it using the libclang.so also present in that directory as follows:
clang main.c -o bin/dlc -I../llvm/tools/clang/include -L../llvm/Release+Asserts/lib/ -lclang
Everything seems to work well.
What is the minimum set of .a files I need to include to make this work? I've tried including absolutely all of the .a files in the build output directory, with them provided to clang/gcc in different orders, without any success. I only need the functions mentioned in libclang's Index.h, but there don't seem to be any resources or documentation on what the various libclang*.a files are for. It would be very helpful to know which files libclang.so pulls in.
The following is supposed to work, as long the whole project has all static libraries (I counted 116 in my Release/lib directory).
clang main.c -o bin/dlc -I../llvm/tools/clang/include ../llvm/Release/lib/*.a
[edit: clang main.c -o bin/dlc -I../llvm/tools/clang/include ../llvm/Release/lib/libclang.a ../llvm/Release/lib/*.a]
Note that the output binary is not static, so you don't need any -static flag for gcc or ld, if you're using this syntax.
If that doesn't work you might need to list the libraries in order: if some library requires a function available in another library, then it may be necessary to list it first in the command line. See comments about link order at:
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Link-Options.html#Link-Options

Creating one C file when compiling multiple sources

I have a set of C files to compile using gcc and make. The build process works fine.
I want to know if I can obtain - during compilation - one C file containing all the source code without any preprocessor macro.
One simple was would be to make a file that included all the other source files.
$cat *.c > metafile.c
This would construct such a file, depending on how you set you 'pragma once' and ifndef's this file would probably not be able to compile on its own.
On the other hand, if what you want in a file where all the preprocessor macro's have been unfolded and evaluated, then the answer is to add the following to gcc:
-save-temps
then the file .ii will contain the unfolded and evaluated macros
If you include all files to the gcc compiler at once you could use
gcc -E main.c other.c another.c
This will also include the stdlib functions maybe use -nostdinc
You can't - normally you invoke the compiler to compile just a single source file, resulting in an object file. Later you call the linker on all of the object files to create the executable - it doesn't have the original C source code available.
You can, however, create a separate shell script that calls gcc with the -E option just to preprocess the source files, and then use the cat utility to put all the sources in a single file.
You can use the -save-temps option to get the intermediate outputs. However it will be one output file per source file. Each source file gets compiled separately and represents a compilation unit which can't be mixed up.
You can also use the -E option, however that will only run the preprocessor and not continue compilation.

link c function in nasm

got a nasm project and i'm calling a c function from it
I put the name of the function in "extern"
and when linking i put all the links together but i can an error of "undefined reference to"
here is my compile/link command
gcc -o Project4 Project4.o array1c.c readdouble.o writedouble.o readarray.o printarray.o addarray.o invertarray.o invertarray2.o invertarray3.o averagearray.o quicksort.c
I would first compile all of your .c files using the "gcc -c" command into object files, then link those resulting .o files (such as "array1c.o" and "quicksort.o") together with your other pre-existing object files and see if that still gives you an undefined reference. That may be an unnecessary step, but I've never combined raw .c files and .o files in a single call to gcc.
You may also have to add an underscore to the beginning of any c-functions called ... I know this an be a platform dependent thing (i.e., Linux typically doesn't need underscores on c-functions whereas OSX and some other UNIX platforms do).
Lastly you could try, using ld, to just link all the object files together at once rather than linking some of the object files together into Project4.o, and then linking that to what you had assembled using nasm (at least that's what I'm assuming you're doing, i.e., you're making a Project4.o, and then calling functions from that in your assembly code).
Hope this helps,
Jason

Resources