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.
Related
In my project I have makefiles which build Solaris kernel modules, and they use gcc to compile files but use ld to link all .o files together into a kernel module. I am trying to include some coverage options like gcov (-fprofile-arcs) or tcov (-xprofile=tcov) in my build, hence I want to replace ld with gcc during linking also.
But as soon as I use replace gcc with ld, the builds start failing with lot of "undefined symbol" errors, even if I use some compile flags and get rid of these errors, the kernel module will not load into my Solaris kernel at all.
For example:
$ /usr/ccs/bin/ld -r -dy -Nstrmod/rpcmod -Nfs/nfs \
-Nmisc/rpcsec -Nmisc/klmmod -Nfs/zfs \
-o debug64/nfssrv \
debug64/nfs_server.o debug64/nfs_srv.o debug64/nfs3_srv.o \
debug64/nfs_acl_srv.o debug64/nfs_auth.o obj64/nfs41_srv.o \
obj64/ctl_ds_srv.o obj64/dserv_server.o
ld works fine but with gcc I get following errors:
/opt/gcc-4.4.4/bin/gcc -m64 -z muldefs \
-Lmod/rpcmod -Lfs/nfs -Lmisc/rpcsec \
-Lmisc/klmmod -Lfs/zfs \
-o obj64/nfssrv \
obj64/nfs_server.o obj64/nfs_srv.o obj64/nfs3_srv.o
obj64/nfs_acl_srv.o obj64/nfs_auth.o obj64/nfs41_srv.o
obj64/ctl_ds_srv.o obj64/dserv_server.o
Undefined first referenced
symbol in file
hz obj64/nfs_server.o
p0 obj64/nfs_server.o
nfs_range_set obj64/nfs41_srv.o
getf obj64/nfs_server.o
log2 obj64/nfs4_state.o
main /usr/lib/amd64/crt1.o
stoi obj64/ctl_ds_srv.o
dmu_object_alloc obj64/dserv_server.o
nvpair_name obj64/nfs4_srv.o
__dtrace_probe_nfss41__i__destroy_encap_session obj64/nfs41_srv.o
__dtrace_probe_nfssrv__i__dscp_freeing_device_entries obj64/ctl_ds_srv.o
mod_install obj64/nfs_server.o
xdr_faststatfs obj64/nfs_server.o
xdr_WRITE3res obj64/nfs_server.o
svc_pool_control obj64/nfs_server.o
Warning the option -L allows to specify a path where to search for libraries, to specify a library you want to link with you (also) have to use the option -l
So a priori you have to add the options -lrpcmod -lnfs -lrpcsec -lklmmod -lzfs
More details in GCC Linking Options
By default, the GNU linker called through the gcc compiler driver will try to create a standard executable. Consequently, if you don't tell it otherwise, ld will use its default linker script, the C startup code and it will look for a main() routine and everything else that makes a valid executable.
I'm not too familiar with Solaris, but would bet this will not be suitable to build kernel modules. I would expect kernel modules will at least require some options like -ffreestanding, -nostdlibs and most likely a non-default linker script that's probably very different from the default one used for applications.
Even if you manage to link your kernel modules this way, I seriously doubt you will be finished. The gcov instrumentation routines most likely do not expect to live within a kernel driver but expect a proper C execution environment (e.g. it will at least expect to fopen() a file to fwrite() its findings). A kernel driver, however, does not have this comfort. You'll probably find yourself confronted with the problem to get the gcov data somehow out of your kernel modules.
Not saying this is not doable, but it certainly will be a lot of work.
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
Setting
Compiler: GHC 7.10.3
I must use two dynamic libraries (libpetsc and libslepc), one of which uses functions from the other. When linking my application, I encounter the following error, which mentions one such symbol (KSPConvergedReasons). NB. my own code does not use this symbol.
user specified .o/.so/.DLL could not be loaded
(dlopen($SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib, 5): Symbol
not found: _KSPConvergedReasons
Referenced from: $SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib
Expected in: flat namespace
in $SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib)
Surely enough, nm -u shows _KSPConvergedReasons as an undefined
symbol (see below).
I don't understand the reason of this behaviour since I first compile
with all the relevant PETSc and SLEPc headers and link against both
.dylibs.
NB:
The symbol in question (KSPConvergedReasons) does exist in the callee library (libpetsc):
$ nm ${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc.3.7.2.dylib | grep KSPConv
000000000110a652 T _KSPConvergedDefault
0000000001109703 T _KSPConvergedDefaultCreate
000000000110b934 T _KSPConvergedDefaultDestroy
0000000001109a96 T _KSPConvergedDefaultSetUIRNorm
000000000110a074 T _KSPConvergedDefaultSetUMIRNorm
000000000106533d T _KSPConvergedLSQR
0000000001743280 D _KSPConvergedReasons
...
Build + link sequence
Build the C code generated from my own library, which in turn uses headers from the two aforementioned libs:
gcc -c -g -w ${SRCDIR}/Internal/InlineC.c -o ${LIBDIR}/InlineC_c.o -I${PETSC_DIR_ARCH}/include -I${PETSC_DIR}/include -I${SLEPC_DIR_ARCH}/include -I${SLEPC_DIR}/include
Link :
stack exec ghci ${SRCDIR}/Spec.hs ${SRCDIR}/Internal/InlineC.hs ${LIBDIR}/InlineC_c.o -- -isrc/ -L${PETSC_DIR_ARCH}/lib -L${SLEPC_DIR_ARCH}/lib -lpetsc -lmpich -lslepc
Question
Why is this happening and how can I fix this?
Thank you in advance for any pointers,
Marco
Undefined symbols in calling dynlib :
$ nm -u libslepc.3.7.1.dylib | grep KSP
_KSPAppendOptionsPrefix
_KSPConvergedReasons
...
I'm trying to get BLAS working with in a FORTRAN 77 program, but so far I've been unsuccesful and I can't figure out how to get going with this. For reference I'm doing this under Ubuntu 12.10.
This is the code of the program I'm trying to compile:
program blastest
implicit none
include 'cblas_f77.h'
end
The file cblas_f77.h resides in /usr/include, and there are both libblas.a and libblas.so (and a bunch of other BLAS related files) in /usr/lib.
How do you configure this to work properly?
So far, I've tried the following:
Note: adding -lblas to either of the options make no difference at all...
Just f77, no options (didn't really expect this to work, but what the heck...):
$ f77 blastest.f -o blastest
MAIN blastest:
Cannot open file cblas_f77.h
/usr/bin/f77: aborting compilation
f77 with include option to find the header file. Now, instead it fails on (despite the file name) not being coded with FORTRAN 77 in mind, so the first six columns are nonempty...
$ f77 blastest.f -o blastest -I/usr/include
MAIN blastest:
Error on line 1 of /usr/include/cblas_f77.h: nondigit in statement label field "/* "
Error on line 2 of /usr/include/cblas_f77.h: labeled continuation line (starts " * cbl")
Error on line 3 of /usr/include/cblas_f77.h: labeled continuation line (starts " * Wri")
...
Full output: http://pastebin.com/eZBzh9N5
Switched to gfortran, to be more flexible with the spacing in the header file:
$ gfortran blastest.f -o blastest -I/usr/include
Warning: cblas_f77.h:9: Illegal preprocessor directive
Warning: cblas_f77.h:10: Illegal preprocessor directive
Warning: cblas_f77.h:12: Illegal preprocessor directive
...
Full output: http://pastebin.com/P71Di9pR
OK, so I guessed I need -cpp to get the preprocessor working. That gave exactly the same output as above. Also, if you keep reading you see that the full output, the compiler is still complaining about labelled continuation lines further down...
I believe that you are using the C library "cblas". I would recompile with this command:
gfortran blastest.f -o blastest -L/usr/lib -lblas
and this should sort it all out. I do not believe (though i am not sure) that you need to make use of the "include" statement.
My toolchain is a recent version of arm-gcc.
I have a piece of code in an assembly file which must be conditionally included/assembled.
.ifdef MACRO_FROM_CMDLINE
Assembly instr1
Assembly instr2
.endif
Encapsulated code is a recent addition.
I have tried both:
gcc -x assembler-with-cpp --defsym MACRO_FROM_CMDLINE=1 <along with other necessary options>
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 <along with other necessary options>
The -D results in "Invalid identifier for .ifdef " and ".endif without .if" errors.
The --defsym results in "MACRO_FROM_CMDLINE=1 : No such file or directory", "unrecognized option --defsym" errors.
The gcc binary drives the compilation process by invoking a number of other programs in sequence to actually perform the various stages of work (compiling, assembling, linking).
When you say:
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 ...
you are asking it to run the source through the C preprocessor, and then run the result through the assembler.
The C preprocessor step will turn:
.ifdef MACRO_FROM_CMDLINE
into:
.ifdef 1
before passing it to the assembler, which then can't make sense of it. This is why you get the "invalid identifier" error. It also explains why using C preprocessor #ifdef fixes the problem.
--defsym doesn't work because it's an option to the assembler, not the gcc driver program. (The gcc driver does understand and pass through some options to some of the programs it invokes, but not all.)
You can, however, pass arbitrary options through to the assembler using the
-Wa,option[,option...]
syntax, which tells the gcc driver to pass those option(s) through to the assembler (as a list of space-separated options).
For example:
gcc -x assembler-with-cpp -Wa,--defsym,MACRO_FROM_CMDLINE=1 ...
adds
--defsym MACRO_FROM_CMDLINE=1
to the list of options passed to as when gcc invokes it, and that's how to make your original .ifdef example work.
You can see the individual programs invoked by gcc, and the options it actually passes to them, by adding the -v option.
In this case, you should see something called cc1 (the actual GCC C compiler binary) invoked with the -E flag (preprocess only) to preprocess the input to a temporary file, and then as invoked on the temporary file to assemble it.
Strange, but it it turns out I needed to use the C syntax in the assembly file.
#ifdef MACRO
Assembly Instruction
Assembly Instruction
#endif
And the macro had to be passed using the -D option.