How to compile a C program without knowing the include files - c

I have some example C code that I'm looking to adapt to suit my needs. Before then I'm trying to compile the example as it is. The C code contains a #include reference, and I can find the .h file in an 'inc' directory. There is also a corresponding 'lib' directory. I am struggling to find the command line I need to compile the code.
So far I've managed to get to the following;
gcc -o amqsinqa -I/opt/mqm/inc amqsinqa.c -L/opt/mqm/lib -lcmqc
But it 'cannot find -lcmqc'. I've looked in lib and quite correctly there is no cmqc. How do I determine what -l option I need here?
The code looks fairly simple, there is the include reference;
#include <cmqc.h>
And the call itself;
MQCONN(QMgrName,&Hcon,&CompCode,&CReason);
If I omit the -l option from the command line I get;
undefined reference to 'MQCONN'
Which isn't a surprise. MQCONN is present in cmqc.h though.

To try to help others, this reference is useful:
64 bit apps: https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q028490_.htm
32 bit apps:
https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q028480_.htm
In summary:
-I is for the product includes, which are (For Linux) usually in /opt/mqm/inc
-L is the path to the libraries in your example which are (For Linux) usually in /opt/mqm/lib (for 32 bit applications) and /opt/mqm/lib64 (for 64 bit
applications)
-l (lower case L) is for the required library/libraries,
and the actual library you need is either:
mqm - server bound C applications (ie -lmqm, which links with libmqm.so)
mqic - client bound C applications (ie -lmqic, which links with libmqic.so)
.. and a suffix of _r if you are building as a threaded application (ie you are linking with -lpthread as well, ie providing -lmqm_r or -lmqic_r which in effect links with libmqm_r.so or libmqic.so)
cmqc.h is the name of the main header file, and there are other cmq*.h headers you can optionally include as well.
If you are using the (stabilized) C++ libraries there's other libraries to include on the command line but that's outside the scope for this answer - see the referenced links

Thanks to all the above for the guidance. Looks like I was missing a few things. This is what I did;
Use nm to identify which .so file contained what I wanted. This returned libmqm.so.
Move that into the -l command, which gave me;
gcc -o amqsinqa -I/opt/mqm/inc amqsinqa.c -L/opt/mqm/lib -lmqm
But it left me with a 'skipping incompatible' warning message followed by a 'cannot find' error message.
Most common Google answer to this issue was a 32/64 bit mismatch, so I searched for a 64 bit version of the same, which ended up being in lib64. So the final compile command is;
gcc -o amqsinqa -I/opt/mqm/inc amqsinqa.c -L/opt/mqm/lib64 -lmqm

You should review the gcc options, in particular the '-m' option,
If you want to build a 32-bit MQ application then you do:
gcc -m32 -o amqsinqa -I/opt/mqm/inc amqsinqa.c -L/opt/mqm/lib -lmqm
If you want to build a 64-bit MQ application then you do:
gcc -m64 -o amqsinqa -I/opt/mqm/inc amqsinqa.c -L/opt/mqm/lib64 -lmqm

Related

ld: warning: directory not found for option: -LC_ID_DYLIB=/usr/lib

I'm using OSX command line gcc and attempting to build a dynamic library. when I do the build I get the following warning. How is it it is not finding this library given /usr/lib is well known? And /usr/lib does indeed exist on my machine
this is what I am using:
gcc -arch i386 cata/*.c -dynamiclib -o build/cata.dylib -LC_ID_DYLIB=/usr/lib
Thanks
the way i solved it was to make it so the string that got stuck in the library (on where to find the library at runtime) was relative to nowhere -- if that makes sense. so it would be forced to use the LD_LOAD_PATH.
I was using the other flags because someone suggested I use them.
so the gcc i ended up using is this:
# my tree is like this
# cata/*.c
# build/*.dylib
#
cd build
gcc -arch i386 ../cata/*.c -dynamiclib -o cata.dylib
Doing this compiles/makes a library in the same directory where it thinks it is 'used' (basically having no path). I am now free to put it somewhere else. When it is later linked at compile time by a different program and then examined using
otool -L
it appears with no path in front of the library name. This is apparently preferable as now when the system goes to try to find it it resorts to looking at the standard libraries and eventually finds it (because I install it to one of the standard locations).
In the original way, otool -L was showing it having a required path of
'build/cata.dylib'
This made it un-findable and which is why i was trying to use the apple documentation to get around the problem.
This doesn't really solve why LC_ID_DYLIB doesn't work. I looked into the Loader.h file (line 643) and it has room for an identifier(0xd), a path, and a structure, so I don't really understand why my path wasn't getting picked up. but its two different topics. Loader.h is runtime and the other is gcc AFAIK. I'm still learning apple.

SysGCC toolchain can't find files in sysroot

I set up this toolchain on my Windows machine for my Pi (raspberry-gcc4.6.3-nosysroot.exe) and then I followed the instructions here to synchronize my sysroot.
I use a library called WiringPi in my project, and I have confirmed that it is in the synchronized sysroot:
Then I attempt to compile it:
arm-linux-gnueabihf-gcc -Wall -O -c main.c
But I get the following error:
fatal error: wiringPi.h: No such file or directory
What do I have to do to make the compiler find the header file? I thought the whole point of synchronizing the sysroot was to make this kind of thing work?
You'll have to let gcc know where to look for the include files via the -I argument. In the case above, -IC:\SysGCC\Raspberry\...\usr\local. You may have to add more than one include path, depending on where the required files are scattered. You can also try to set gcc's environment variable(s).
Finding out the correct include path can be a little tedious (see above: should it be local\ or local\include\?). Maybe you can find the environment setting for all default include paths on your Pi and just copy it over to your Windows machine.
Edit: Think I got it: echo | gcc -v -E -

gcc switches - what do these do?

I am new with using gcc and so I have a couple of questions.
What do the following switches accomplish:
gcc -v -lm -lfftw3 code.c
I know that lfftw3 is an .h file used with code.c but why is it part of the command?
I couldn't find out what -lm does in my search. What does it do?
I think I found out -v causes gcc to display programs invoked by it.
-l specifies a library to include. In this case, you're including the math library (-lm) and the fftw3 library (-lffw3). The library will be somewhere in your library path, possibly /usr/lib, and will be named something like libffw3.so
From GCC's man page:
-v Print (on standard error output) the commands executed to run the
stages of compilation. Also print the version number of the
compiler driver program and of the preprocessor and the compiler
proper.
-l library
Search the library named library when linking. (The second
alternative with the library as a separate argument is only for
POSIX compliance and is not recommended.)
It makes a difference where in the command you write this option;
the linker searches and processes libraries and object files in the
order they are specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers to functions in
z, those functions may not be loaded.
The linker searches a standard list of directories for the library,
which is actually a file named liblibrary.a. The linker then uses
this file as if it had been specified precisely by name.
The directories searched include several standard system
directories plus any that you specify with -L.
Normally the files found this way are library files---archive files
whose members are object files. The linker handles an archive file
by scanning through it for members which define symbols that have
so far been referenced but not defined. But if the file that is
found is an ordinary object file, it is linked in the usual
fashion. The only difference between using an -l option and
specifying a file name is that -l surrounds library with lib and .a
and searches several directories.
libm is the library that math.h uses, so -lm includes that library. You might want to get a better grasp of the concept of linking. Basically, that switch adds a bunch of compiled code to your program.
-lm links your program with the math library.
-v is the verbose (extra ouput) flag for the compiler.
-lfftw3 links your program with fftw3 library.
You just include headers by using #include "fftw3.h". If you want to actually include the code associated to it, you need to link it. -l is for that. Linking with libraries.
arguments starting with -l specify a library which is linked into the program. Like Pablo Santa Cruz said, -lm is the standard math library, -lfftw3 is a library for fourier transformation.
Try man when you're trying to learn about a command.
From man gcc
-v Print (on standard error output) the commands executed to run the
stages of compilation. Also print the version number of the
com-
piler driver program and of the preprocessor and the compiler
proper.
As Pablo stated, -lm links your math library.
-lfftw3 links in a library used for Fourier transforms. The project page, with more info can be found here:
http://www.fftw.org/
The net gist of all these statements is that they compile your code file into a program, which will be named the default (a.out) and is dependent on function calls from the math and fourier transform libs. The -v statement just helps you keep track of the compilation process and diagnose errors should occur.
In addition to man gcc which should be the first stop for questions about any command, you can also try the almost standard --help option. Even for commands that don't support it, an unsupported option usually causes it to print an error containing usage information that should hint at a similar option. In this case, gcc will display a terse (for gcc, its only about 50 lines long) help summary listing the small number of options that are understood by the gcc program itself rather than passed on to its component programs. After the description of the --help option itself, it lists --target-help and -v --help as ways to get more information about the target architecture and the component programs.
My MinGW GCC 3.4.5 installation generates more than 1200 lines of output from gcc -v --help on Windows XP. I'm pretty sure that doesn't get much smaller in other installations.
It would also be a good idea to read the official manual for GCC. It is also helpful to read the documentation for the linker (ld) and assembler (often gas or just as, but it may be some platform specific assembler as well); aside from a platform-specific assembler, these are documented as part of the binutils collection.
General familiarity with the command line style of Unix tools is also helpful. The idea that a single-character option's value might not be delimited from the option name is a convention that goes back essentially as far as Unix does. The modern convention (promulgated by GNU) that multiple-character option names are introduced by -- instead of just - implies that -lm might be a synonym for -l m (or the pair of options -l -m in some conventions but that happens not to be the case for gcc) but it is probably not a single option named -lm. You will see a similar pattern with the -f options that control specific optimizations or the -W options that control warnings, for example.

AIX xlC cross-compilation/linkage for C++ not finding C symbols

I am attempting to cross-compile on AIX with the xlc/xlC compilers.
The code compiles successfully when it uses the default settings on another machine. The code actually successfully compiles with the cross-compilation, but the problem comes from the linker. This is the command which links the objects together:
$(CHILD_OS)/usr/vacpp/bin/xlC -q32 -qnolib -brtl -o $(EXECUTABLE) $(OBJECT_FILES)
-L$(CHILD_OS)/usr/lib
-L$(CHILD_OS)/usr/vacpp/lib/profiled
-L$(CHILD_OS)/usr/vacpp/lib
-L$(CHILD_OS)/usr/vac/lib
-L$(CHILD_OS)/usr/lib
-lc -lC -lnsl -lpthread
-F$(CHILD_OS)$(CUSTOM_CONFIG_FILE_LOCATION)
When I attempt to link the code, I get several Undefined symbols:
.setsockopt(int,int,int,const void*,unsigned long), .socket(int,int,int), .connect(int,const sockaddr*,unsigned long), etc.
I have discovered that the symbols missing are from the standard c library, libc.a. When I looked up the symbols with nm for the libc.a that is being picked up, the symbols do indeed exist. I am guessing that there might be a problem with the C++ being unable to read the C objects, but I am truly shooting in the dark.
Sound like it might be a C++ name mangling problem.
Run nm on the object files to find out the symbols that they are looking for. Then compare the exact names against the libraries.
Then check the compilation commands, to ensure that the right version of the header files is being included - maybe it's including the parent OS's copy by mistake?
I was eventually able to get around this. It looks like I was using the C++ compiler for .c files. Using the xlc compiler instead of the xlC compiler for C files fixed this problem.

Portable way to link statically against one of the libraries

I am creating a utility which depends on libassuan aside other depends. While these ‘others’ provide shared libraries, libassuan comes with static one only.
libassuan comes with simple libassuan-config tool which is meant to provide CFLAGS & LDFLAGS for the compiler/linker to use. These LDFLAGS refer to the library as -lassuan.
The result of standard call of make is then:
cc -I/usr/include/libmirage -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -lmirage -lglib-2.0 -L/usr/lib64 -lassuan -o mirage2iso mirage2iso.c mirage-getopt.o mirage-wrapper.o mirage-password.o
mirage-password.o: In function `mirage_input_password':
mirage-password.c:(.text+0x1f): undefined reference to `assuan_pipe_connect'
mirage-password.c:(.text+0x32): undefined reference to `assuan_strerror'
collect2: ld returned 1 exit status
make: *** [mirage2iso] Error 1
(I've just started writing this unit and that's why there aren't more errors)
So, if I understand the result correctly, gcc doesn't want to link the app to libassuan.a.
Using -static here will cause gcc to prefer static libraries over shared which is unindented. I've seen solution suggesting using something like that:
-Wl,-Bstatic -lassuan -Wl,-Bdynamic
but I don't think it would be a portable one.
I think the best solution would be to provide full path to the static library file but libassuan-config doesn't provide much of help (all I can get from it is -L/usr/lib64 -lassuan).
Maybe I should just try to create the static library path by ‘parsing’ returned LDFLAGS and using -L for the directory name and -l for the library name — and then hoping that in all cases libassuan-config will return it like that.
What do you think about that? Is there any good, simple and portable solution to resolve the issue?
PS. Please note that although I'm referring to gcc here, I would like to use something that will work fine with other compilers.
PS2. One additional question: if package does install static library only, returning such LDFLAGS instead of full .la path can be considered as a bug?
gcc will link to libassuan.a if it doesn't find libassuan.so
It's probably the order symbols are looked up in the static library when you link. The order matters.
)
Assuming gcc can find libassuan.a and it actually provides the functions the linker complains about, try:
cc -I/usr/include/libmirage -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -lmirage -lglib-2.0 -L/usr/lib64 -o mirage2iso mirage2iso.c mirage-getopt.o mirage-wrapper.o mirage-password.o -lassuan
Since you say libassuan is under /usr/lib64 it's probably a 64 bit library, are your app and the other libraries 64 bit as well ?
Compiler's command-line options are not a portable thing. There's no standard for it. Every compiler uses its own and several can merely informally agree to comply with each other in command-line format. The most portable way for your linking is to use libassuan-config, of course. I think, it can generate not only flags for gcc, but for other compilers as well. If it can't, then no portable way exists, I suppose (other than CMake or something on higher level).
The command line to cc you shown is totally correct. If you have a static library libassuan.la and path to it is supplied to -L option, then the compiler does link against it. You can see it from its output: has it not found the static library, would it complain with error message like "can't find -lassuan". I
Moreover, if no libassuan.so is found, then compiler links against your library statically, even if you haven't used -Wl,-Bstatic stuff or -static flag.
Your problem may be in persistence of several versions of libassuan in your system. Other that that, I don't see any errors in what you've provided.
Which directory is libassuan.a in
I think the first error is not gcc doesn't want to link the app to libassuan.a it is more gcc does not know where libassuan.a . You need to pass gcc a -L parameter giving the path to libassuan.a .
e.g.
-L /home/path

Resources