Getting the GCC include path with GNU Autotools - c

I'm writing an implementation of the C preprocessor that, when running on Linux, needs to know the path on which to find header files. This can be obtained by running gcc -v. I want to compile the results into the binary of my preprocessor rather than having to invoke gcc -v on every run, so I'm currently thinking of writing a Python script to be run at compile time, that would obtain the path and write it into a small C source file to be included in the build.
On the other hand, I get the impression GNU Autotools is basically the specialist in obtaining system-specific information to be used at build time. Does Autotools have the ability to obtain the #include path in such a way that it can be incorporated as a string into the program being built (as opposed to being used for the build process)? If so, how?

If you want to get the internal include/ directory used by GCC, run the gcc -print-file-name=include command, e.g. in shell syntax
the_gcc_include_dir=$(gcc -print-file-name=include)
This $the_gcc_include_dirdirectory contains files like <stdarg.h> and <stddef.h> and many others.
You also want the include-fixed/ directory, so
the_gcc_include_fixed_dir=$(gcc -print-file-name=include-fixed)
This $the_gcc_include_fixed_dir contains files like <limits.h> and also a useful README
You probably don't need autotools in your case.

I ended up parsing gcc's include path with a Python script:
print 'string gcc_include_path[] = {'
for s in sys.stdin:
if s[0] == ' ':
s = s.strip()
print '\t"'+s+'",'
print '};'
and calling it from Makefile:
echo | cpp -Wp,-v 2>&1 >/dev/null | python include_path.py >include_path

Related

What is the difference between /usr/include/linux and /usr/include/x86_64-linux-gnu/

I'm very new to native C programming and now I'm trying to configure my IDE to set up include paths correctly. Since I would like to navigate by sys/xxx.h files I added
/usr/include/x86_64-linux-gnu/
to my include path. But there is also /usr/include/linux which seems contains the same headers also. So what is the difference between them? And which one should I use actually?
I can tell you immediately that the directories /usr/include/linux and /usr/include/asm should never be included in a list of system header directories. The headers in those directories are meant to be used as #include <linux/whatever.h> or #include <asm/whatever.h>, not as #include <whatever.h>.
The rest of the answer to this question depends on exactly which "distribution" of Linux you are using, so I can't just say it. Fortunately, there is a way to get the compiler to tell you. Run this command (exactly as shown) in a terminal window:
LC_ALL=C gcc -v -xc -E /dev/null 2>&1 |
sed -ne '/search starts here/,/End of search list/p'
You will get output that looks something like this, but the details may be slightly different:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
The directories listed are the directories you should configure your IDE to look for system headers in, for purpose of looking up declarations and whatnot. However, you should not configure your IDE to pass any of these directories to the compiler as -I directories. It already knows to use them, it doesn't need to be told again, and telling it again can mess things up (for instance, the order of the above directories matters).
As an application programmer you don't need to worry about which headers "belong" in which directories. That's entirely the compiler and C library developers and Linux distribution maintainers' task.

Problems with linking a library with a c program in linux

I want to run serial commands from a Bealgebone to a 4Dsystems display. Therefore I copied the c library found here into a directory and created a test program main.c:
#include "Picaso_const4D.h"
#include "Picaso_Serial_4DLibrary.h"
int main(int argc,char *argv[])
{
OpenComm("/dev/ttyUSB0", B115200); // Matches with the display "Comms" rate
gfx_BGcolour(0xFFFF);
gfx_Cls();
gfx_CircleFilled(120,160,80,BLUE);
while (1) {}
}
Now when I do gcc -o main main.c its says
main.c:2:37: fatal error: Picaso_Serial_4DLibrary.h: No such file or
directory
So I try linking it:
gcc main.c -L. -lPICASO_SERIAL_4DLIBRARY
which gives me the same error. Then I tried to create a static library:
gcc -Wall -g -c -o PICASO_SERIAL_4DLIBRARY PICASO_SERIAL_4DLIBRARY.C
which gives me this:
PICASO_SERIAL_4DLIBRARY.C:1:21: fatal error: windows.h: No such file
or directory compilation terminated.
What am I doing wrong? the git page clearly says this library is created for people who do not run windows.
Thanks in advance!
You're not getting a linker error; you're getting a preprocessor error. Specifically, your preprocessor can't find Picaso_Serial_4DLibrary.h. Make sure that it's in your include path; you can add directories to your include path using the -I argument to gcc.
You've had two problems. First was the picaso_whatever.h file that couldn't be found. You fixed that with the -I you added. But, now, the picaso.h wants windows.h
What are you building on? WinX or BSD/Linux?
If you're compiling on WinX, you need to install the "platform sdk" for visual studio.
If you're using mingw or cygwin, you need to do something else.
If on WinX, cd to the C: directory. Do find . -type f -name windows.h and add a -I for the containing directory.
If under Linux, repeat the find at the source tree top level. Otherwise, there is probably some compatibility cross-build library that you need to install.
Or, you'll have to find WinX that has it as Picaso clearly includes it. You could try commenting out one or more of the #include's for it and see if things are better or worse.
If you can't find a real one, create an empty windows.h and add -I to it and see how bad [or good] things are.
You may need the mingw cross-compiler. See https://forums.wxwidgets.org/viewtopic.php?t=7729
UPDATE:
Okay ... Wow ... You are on the right track and close, but this is, IMO, ugly WinX stuff.
The primary need of Picaso is getting a serial comm port connection, so the need from within windows.h is [thankfully] minimal. It needs basic boilerplate definitions for WORD, DWORD, etc.
mingw or cygwin will provide their own copies of windows.h. These are "clean room" reimplementations, so no copyright issues.
mingw is a collection of compile/build tools that let you use gcc/ld/make build utilities.
cygwin is more like: I'd like a complete shell-like environment similar to BSD/Linux. You get bash, ls, gcc, tar, and just about any GNU utility you want.
Caveat: I use cygwin, but have never used mingw. The mingw version of windows.h [and a suite of .h files that it includes underneath], being open source, can be reused by other projects (e.g. cygwin, wine).
Under Linux, wine (windows emulator) is a program/suite that attempts to allow you to run WinX binaries under Linux (e.g. wine mywinpgm).
I git cloned the Picaso library and after some fiddling, I was able to get it to compile after pointing it to wine's version of windows.h
Picaso's OpenComm is doing CreateFile [a win32 API call]. So, you'll probably need cygwin. You're opening /dev/ttyUSB0. /dev/* implies cygwin. But, /dev/ttyUSB0 is a Linux-like name. You may need some WinX-style name like "COM:" or whatever. Under the cygwin terminal [which gives you a bash prompt], do ls /dev and see what's available.
You can get cygwin from: http://cygwin.com/ If you have a 64 bit system, be sure to use the 64 bit version of the installer: setup-x86_64.exe It's semi-graphical and will want two directories, one for the "root" FS and one to store packages. On my system, I use C:\cygwin64 and C:\cygwin64_packages--YMMV.
Note that the installer won't install gcc by default. You can [graphically] select which packages to install. You may also need some "devel" packages. They have libraries and .h files that a non-developer wouldn't need. As, docs mention, you can rerun the installer as often as you need. You can add packages that you forgot to specify or even remove ones that you installed that you don't need anymore.
Remember that you'll need to adjust makefile -I and/or -L option appropriately. Also, when building the picaso library, gcc generated a ton of warnings about overflow of a "large integer". The code was doing:
#define control_code -279
unsigned char buf[2];
buf[0] = control_code >> 8;
buf[1] = control_code;
The code is okay, and the warning is correct [because the code is sloppy]. If the code had done:
#define control_code -279
unsigned char buf[2];
buf[0] = (unsigned) control_code >> 8;
buf[1] = (unsigned) control_code;
it probably would have been silent. Use -Wno-overflow in your Makefile to get rid of the warnings rather that edit 50 or so lines

Old gcc compiler on matlab

I am using MATLAB on the Linux MINT. I have a C program for which I want to used mex command as follows:
mex /home/.../binary.c -output binary_m
but I get the following error
Warning: You are using gcc version "4.8.1-10ubuntu9)". The version
currently supported with MEX is "4.4.6".
For a list of currently supported compilers see:
http://www.mathworks.com/support/compilers/current_release/
/home/.../binary.c:43:19: fatal error: binary.h: No such file or directory
#include "binary.h"
^
compilation terminated.
mex: compile of ' "/home/.../binary.c"' failed.
I think that I have to downgrade the gcc compiler on the MATLAB but I don't know how.
Any help is appreciate it.
Regards
This has nothing to do with the warning regarding the compiler version; don't pay attention to that, you will be fine. You might have had problems trying to compile c++11 sources, depending on your Matlab version, compiler version and mex command flags, but this is not your case.
Here is the problem: your C program binary.c contains an #include statement of the file binary.h which is not found by Matlab (although I trust you put it in the same directory than the C file?) because the directory that contains your C sources is not in the Matlab path.
To fix the problem, simply change directory to where binary.c is, and mex your file there. You can automate the process doing something like:
source_dir = '/home/.../';
current_dir = fileparts(mfilename('fullpath'));
cd source_dir;
% do something
cd current_dir;

Running a C program in Linux

Can someone explain to me why, in particular, we are using ./a.out to run a program?
Is there any meaning behind this?
Can someone please provide an explanation?
The name stands for "assembler output", and was (and still is) the default name for the executable generated by the compiler. The reason you need ./ in front of it is because the current directory (.) is not in $PATH therefore the path to the executable must be explicitly given.
If you mean the ./ part, it's for safety. Windows by default appends current directory to PATH, which is bad (there's a risk of DLL injection, and so on).
If you mean a.out part, it's just a name (which came from name of format a.out), which you can change by modifying gcc -o parameter.
When running an executable like a shell like bash the executable must be in your PATH environment variable for bash to locate and run the program.
The ./ prefix is a shorthand way of specifying the full path to the executable, so that bash does not need to the consult the PATH variable (which usually does not contain the current directory) to run it.
[For a.out (short for "assembler output"), it is the default executable output for a compiler like gcc if no output filename is specified.]
It'd be worth you looking a bit more into C and the way that C programs are compiled.
Essentially, your source code is sent to the preprocessor, where directives like #define and #include are loaded (e.g. into memory). So any libraries you want to use are loaded, e.g.
#include <math.h>
will basically 'paste' the contents of math.h into source code at the point at which it is defined.
Once all this stuff has been expanded out, the compiler turns your source code into object code, which is your source in binary code. a.out is the default name for output if you do not specify a build name.
gcc -o mynewprogram mynewprogram.c
a.out is the default name for the compiler. AFAIK it is because the linking process is skipped and it is not compiled as an object or library.

Including a library (lsusb) in a C program

I am still fairly new to programming with C and I am working on a program where I want to control the power to various ports on a hub I have. That is, however, not the issue I am having right now.
I found a program online that does what I want I am trying to compile it. However it uses #include<lsusb.h>. lsusb is located in a totally different folder than the file I am wanting to run (and not in a sub folder) and when I try to compile it, I, logically enough, get the error that the file lsusb.h is not found.
How can I link to this file so that it can be found?
This is more of a GCC toolchain question than a C question (although most C compilers do use the same Unixy flags).
The braces around the include file (<>) indicate you want the compiler to search its standard search path for the include file. So you can get access to that new include file either by putting it into a directory on your standard include file search path yourself, or by adding its directory to the file search path. With GCC you do the latter by giving gcc the flag -I"directoryname" where "directoryname" is the full file path to where you are keeping that new include file of yours.
Once your compiler finds it, your linker may have the exact same problem with the library file itself ("liblsusb.a"?). You fix that the same way. The flag GCC's linker will want is -L instead of -I.
See the "-I" parameter in the gcc man page. It allows you specify a directory in which to find a header file. See also -l and -L.
Or try #include "../../path_to_the_file/lsusb.h"

Resources