I'm using gfortran [GNU Fortran (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)] on a Fedora 20 x86_64 to compile a bunch of Fortran 77 code which refers to 'iargc' function in the following manner:
bin2D2nc.f:31: integer iargc,strlen1
bin2D2nc.f:32: external iargc,strlen1
bin2D2nc.f:44: i=iargc()
When the make script reaches the compilation comand bellow,
gfortran -O3 -ffixed-line-length-132 -fall-intrinsics -I/home/santiago/Install/netcdf_sam/include -o bin2D2nc -I./SRC ./SRC/bin2D2nc.f ./SRC/hbuf_lib.f ./SRC/cape.f ./SRC/cin.f -L/home/santiago/Install/netcdf_sam/lib -lnetcdf -L/usr/lib64 -lpthread
I receive these messages:
bin2D2nc.f:(.text+0x14): undefined reference to `iargc_'
collect2: error: ld returned 1 exit status
make: ** [bin2D2nc] Erro 1
I'm not the author of this code. As far as I know, I set up correctly the library paths in the makefile.
I have found that 'iargc' is a routine for backward compability with GNU Fotran 77, but I don't understand it deeply.
Could someone give some advise to surpass this problem?
The problem is very similar to Fixing FORTRAN IV warning: "The number of arguments is incompatible with intrinsinc procedure, assume 'external' " but the difference is that in the other question there was an external function present and the similarity with an intrinsic was inadvertent, but you are calling the intrinsic on purpose.
The statement
EXTERNAL IARGC
meant that IARGC is an external or an intrinsic function in FORTRAN 66, but in "modern Fortran" 77 and later it means that it is an external function only.
But you need to call the intrinsic function https://gcc.gnu.org/onlinedocs/gfortran/IARGC.html .
You should use
INTRINSIC IARGC
or even just delete IARGC from the EXTERNAL statement without adding anything else. The compiler will then stop searching for a non-existent external function and will use the intrinsic.
A final note, IARGC itself is not standard Fortran, ut it shouldn't matter here.
Related
While developping a bare metal firmware in C for a RV32IM target (RISC-V), I encountered a linking error when LTO is enabled:
/home/duranda/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/bin/ld: /tmp/firmware.elf.5cZNyC.ltrans0.ltrans.o: in function `.L0 ':
/home/duranda/whatever/firmware.c:493: undefined reference to `memset'
There are however no call to memset in my firmware. The memset is inserted by GCC during optimization as described here. The build is optimized for size using GCC -Os and -flto -fuse-linker-plugin flags. In addition, the -fno-builtin-memset -nostdinc -fno-tree-loop-distribute-patterns -nostdlib -ffreestanding flags are used to prevent the use of memset during optimization and to not include standard libs.
How to prevent memset insertion during LTO? Note that the firmware should not be linked against libc. I also tried providing a custom implementation of memset but the linker does not want to use it for memset inserted during optimization (still throws undefined reference).
I hit similar issue servers years ago and tried to fixed that, but it turns out I misunderstanding the meaning of -fno-builtin[1], -fno-builtin not guaranteed GCC won't call memcpy, memmove or memset implicitly.
I guess the simplest solution is, DO NOT compile your libc.c with -flto, or in another word, compile libc.c with -fno-lto.
That's my guess about what happen, I don't have know how to reproduce what you see, so it might incorrect,
During the first phase of LTO, LTO will collect any symbol you used in program
And then ask linker to provide those files, and discard any unused symbol.
Then read those files into GCC and optimize again, in this moment gcc using some built-in function to optimize or code gen, but it not pull-in before.
The symbol reference is created at LTO stage, which is too late pull in any symbol in current GCC LTO flow, and in this case, memset is discard in earlier stage...
So you might have question about why compile libc.c with -fno-lto will work? because if it didn't involved into LTO flow, which means it won't be discarded in the LTO flow.
Some sample program to show the gcc will call memset even you compile with -fno-builtin, aarch64 gcc and riscv gcc will generate a function call to memset.
// $ riscv64-unknown-elf-gcc x.c -o - -O3 -S -fno-builtin
struct bar {
int a[100];
};
struct bar y;
void foo(){
struct bar x = {{0}};
y = x;
}
Here is the corresponding gcc source code[2] for this case.
[1] https://gcc.gnu.org/pipermail/gcc-patches/2014-August/397382.html
[2] https://github.com/riscv/riscv-gcc/blob/riscv-gcc-10.2.0/gcc/expr.c#L3143
I'm not sure -fno-builtin-* does what you think it does. If you use those flags, then GCC will try to call an external function. If you don't use those flags, GCC will instead just insert inline code instead of relying on the library.
So it would appear to me you should simply not use any -fno-builtin flags.
I write NASM (netwide assembler) program and for some reasons I needed to use some functions written in C. So, I tried to link compiled C object files with compiled Assembly objects using ld link editor. I did it by this way :
ld -m elf_x86_64 -lc --dynamic-linker=/lib64/ld-linux-x86-64.so.2 object_files -o program.
And it didn't want to link and work long enough until I picked up the necessary parameters. Now this works as expected with this parameter set. But I don't understand the meaning of -lc and --dynamic-linker=/lib64/ld-linux-x86-64.so.2. What do they do ?
-lc - link c standard library
--dynamic-linker=/lib64/ld-linux-x86-64.so.2. - set the program loader. Linux ELF binaries have a field for this.
Afaik the latter is needed even for static binaries, anything other will confuse the loader, and it won't execute.
man ld lists its parameters.
I am running GnuCOBOL on Windows from command line to compile and link a COBOL program. I have been able to produce a functioning Hello World program.
The COBOL program I now want to build is quite simple, but calls routines that are available in a C library I have built using another build environment. I have exchanged some names and paths for anonymity.
The lib is called mysrc.lib, and is placed at C:\dev\foo. I compile and link with the command
cobc -x -fword-continuation=ok -ffold-call=LOWER c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc
It seems to find the lib file, because if I change the name of the lib file to something that doesn't exist, it complains about not finding it.
cobc -x -fword-continuation=ok -ffold-call=LOWER c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc2
C:\GnuCOBOL\bin/ld.exe: cannot find -lmysrc2
collect2.exe: error: ld returned 1 exit status
However, when I run the program, it cannot find the routines in mysrc. The first C routine in mysrc that is called from the program cobsim.cob is named dbadr4. When I try to run the resulting cobsim.exe, I get the following error:
libcob: module 'DBADR4' not found
I can also use the flag -fstatic-call to get the link error already when linking.
cobc -x -fword-continuation=ok -ffold-call=LOWER -fstatic-call c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc
.\cob14860_0.o:cob14860_0.c:(.text+0x14f): undefined reference to `dbadr4'
It doesn't seem to matter which order I place the switches and arguments. Including or excluding the -ffold-call=LOWER flag has no effect, apart from the link error complaining about not finding the routine in upper or lower case. I have multiple other programs calling these routines without problem, including C programs and this specific COBOL program compiled and linked with another compiler and linker on another platform.
Any suggestions?
EDIT: Adding requested information.
Output when adding -g -v flags (some information removed or altered for anonymity):
cobc (GnuCOBOL) 3.0-rc1.0
Built May 05 2018 21:41:43 Packaged Apr 22 2018 22:26:37 UTC
C version (MinGW) "6.3.0"
loading standard configuration file 'default.conf'
command line: cobc -x -save-temps -fword-continuation=ok -ffold-call=LOWER -fstatic-call -L C:\dev\foo -l mysrc -o C:\test\MULTI\cobsim.EXE -g -v C:\test\MULTI\cobsim.cob
preprocessing: C:\test\MULTI\cobsim.cob -> cobsim.i
return status: 0
parsing: cobsim.i (C:\test\MULTI\cobsim.cob)
return status: 0
translating: cobsim.i -> cobsim.c (C:\test\MULTI\cobsim.cob)
executing: gcc -c -I"C:\GnuCOBOL\include" -g -o "cobsim.o" "cobsim.c"
return status: 0
executing: gcc -Wl,--export-all-symbols -Wl,--enable-auto-import
-Wl,--enable-auto-image-base -o "C:\test\MULTI\cobsim.EXE"
"cobsim.o" -L"C:\GnuCOBOL\lib"
-L"C:\dev\foo" -L/mingw/lib
-lcob -lm -lgmp -L/mingw/lib -lintl -lpdcurses -l"mysrc"
cobsim.o: In function `simple_':
cobsim.c:112: undefined reference to `dbadr4'
And snippets of the program code, including the call to dbadr4:
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SQL005.
05 SQL005-001 PIC X(1) VALUE " ".
01 SQLPAA.
05 SQLPAA-001 USAGE POINTER.
05 SQLPAA-002 USAGE POINTER.
05 SQLPAA-003 USAGE POINTER.
05 SQLPAA-004 USAGE POINTER.
PROCEDURE DIVISION.
MAIN SECTION.
DO-IT.
CALL "DBADR4" USING SQLPAA-001 SQL005
EDIT 2: Missed adding the DBADR4 function declaration.
void dbadr4(void** addr, const int varibl[1])
The COBOL code is originally Embedded SQL/COBOL code, the call to DBADR4 and the SQL005 and SQLPAA data blocks have been automatically generated. The dbadr4 code is originally Ada code, the C routine declaration has been automatically generated. This generated COBOL code calling this generated C code works fine on HP OpenVMS, where we use HP's COBOL compiler and linker, and has done so for many years.
My simple program compTest.c
#include<stdio.h>
#include<complex.h>
int main(void)
{
double complex z = 1.0 + 1.0 * I;
printf("|z| = %.4f\n", cabs(z));
return 0;
}
When using the standard library and compiling with gcc on a Linux system do I need to include the -lm flag for it to work?
Example:
gcc -o executableName fileName.c -lm
When I don't I get the following:
/tmp/cc1o7rtt.o: In function `main':
comTest.c:(.text+0x35): undefined reference to `cabs'
collect2: error: ld returned 1 exit status
It seems that you've already discovered that the answer is yes.
The -lm flag tells the linker to link the math library, which contains, among other things, the code for the cabs function. (This is a gcc/Linux issue, not a C language issue.)
The Linux man page for cabs specifically says Link with -lm.
(In general, if you want to call any library function and you're not 100% certain how to use it, read the man page.)
I have need to compile and statically link a Chicken program. I expect to use many extensions, most notably http-client.
I can compile the source with the following command:
csc -compile-syntax -static linux-setup.scm
or
csc -R http-client -compile-syntax -static linux-setup.scm
But when I run it, I get the following error:
Error: (require) cannot load extension: http-client
Call history:
##sys#require <--
I have also tried (declare (uses http-client)) in the source, with no success:
linux-setup.o: In function `f_369':
/mnt/data/Documents/Programming/chicken-scheme/linux-setup/linux-setup.c:219:
undefined reference to `C_http_2dclient_toplevel'
collect2: error: ld returned 1 exit status
Error: shell command terminated with non-zero exit status 256: 'gcc' 'linux-setup.o'
-o 'linux-setup' -L"/usr/lib" -Wl,-R"/usr/lib" -static '/usr/lib/libchicken.a' -lm -ldl
Static linking is something I need. This is not an XY problem. I need my executables to run on a freshly-installed Linux system with no dependancies. This is the primary reason I switched from Common Lisp to Scheme in the first place.
What am I doing wrong, please?
Assuming your program is in a-program.scm file:
csc -deploy a-program.scm
cd a-program/
chicken-install -deploy -p $PWD http-client
...et voilĂ !
edit: turns out that the proper answer to the problem posted is solved in this document: http://www.foldling.org/scheme.html#compiling-statically-linked-chicken-scheme-programs-with-extensions