Question

I am compiling one program called nauty. This program uses a canonical function name getline which is also part of the standard GNU C library.

Is it possible to tell GCC at compile time to use this program defined function?

Was it helpful?

Solution

One solution:

Now you have declaration of the function in some application .h file something like:

int getline(...); // the custon getline

Change that to:

int application_getline(...); // the custon getline
#define getline application_getline

I think that should do it. It will also fix the .c file where the function is defined, assuming it includes that .h file.

Also, use grep or "find in files" of editor to make sure that every place where that macro takes effect, it will not cause trouble.

Important: in every file, make sure that .h file included after any standard headers which may use getline symbol. You do not want that macro to take effect in those...

Note: this is an ugly hack. Then again, almost everything involving C pre-processor macros can be considered an ugly hack, by some criteria ;). Then again, getting existing incompatible code bases to co-operate and work together is often a case where a hack is acceptable, especially if long term maintenance is not a concern.

Note2: As per this answer and as pointed out in a comment, this is undefined behavior by C standard. Keep this in mind, if intention is to maintain the software for longer then just getting a working executable binary one time. But I added a better solution.

OTHER TIPS

Note that you may trigger undefined behavior if the GCC header where standard getline is defined is actually used in your code. These are the relevant information sources (emphasis mine):

The libc manual:

1.3.3 Reserved Names

The names of all library types, macros, variables and functions that come from the ISO C standard are reserved unconditionally; your program may not redefine these names. All other library names are reserved if your program explicitly includes the header file that defines or declares them. There are several reasons for these restrictions:

[...]

and the C99 draft standard (N1256):

7.1.3 Reserved identifiers

1

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

[...]

2

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

3

If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

Thus even the macro trick suggested in another post will invoke undefined behavior if you include the header of getline in your code.

Unfortunately, in this case the only safe bet is to manually rename all getline invocations.

C demands unique function names. but you can use -fno-builtin or -ffreestanding gcc flags. see description about this flags in gcc man page.

A common approach is to use prefixes which form some sort of namespace. Sometimes you can see macros used for this to make changing the namespace name easier, e.g.

#define MYAPP(f) myapp_##f

Which is then used like

int MYAPP(add)(int a, int b) {
    return a + b;
}

This defines a function myapp_add which you can also invoke like

MYAPP(add)(3, 5);

This standards compliance issue started to bug me, so I did a bit of experimenting. Here's a 2nd answer, which is possibly better then the currently accepted answer of mine.

First, solution:

Just define macro _XOPEN_SOURCE with value 699, by adding this to compiler command line options

-D_XOPEN_SOURCE=699

How exactly, that depends on applications build system, but one probably working way would be to define CFLAGS environment variable, and see if it takes effect when rebuilding:

export CFLAGS="-D_XOPEN_SOURCE=699"

Other alternative would be to add #define _XOPEN_SOURCE 699 before includes in every .c file of the application, in case it uses some esoteric build system and you can't get it added to compile options, but doing it from command line is by far preferable.

Then some explanation:

Man page of getline specifies, that getline is defined only under certain standards, such as if _XOPEN_SOURCE>=700. So, by defining a smaller value before including the relevant file, we exclude the library declaration. More information about these feature-test macros is found in GNU libc manual.

I expected there to be some linker issues too, but there weren't, and my investigation resulted this question here. To summarize, linker will prefer symbol from linked object files (at least with gcc), and will only look at dynamic libraries if it has not found symbol otherwise. So, since getline is not ISO C symbol, GNU libc documentation quoted in this answer seems to imply, that after using the _XOPEN_SOURCE trick of this answer, it's ok to use it in an application. Still, beware of other libraries using the POSIX getline and ending up calling application's function (probably with different parameters, resulting in undefined behaviour, probably a crash).

Here is a neat solution to your problem. The trick is LD_PRELOAD. I have done the similar thing in one of my question post.See the following. Hack the standard function in library and call the native library function afterwards

You can defined the getline() in the separate file. This will make the design clean too. Now, compile that c file; $gcc -c -g -fPIC <file.c>. This will create the file.o. Now, make the shared object of it. -g for debugging. -fPIC for position independent code. This will help to save the RAM SIZE. The text segment will be shared, if you specify the -fPIC option.

$gcc -shared libfile.so file.o

Now, link your main file with this shared object.

gcc -g main.c -o main.out -lfile

while executing, use the LD_PRELOAD, this will use your library instead of the native API.

$LD_PRELOAD=<path to libfile.so>/libfile.so ./main.out

If you like my answer,then please appreciate. I have done the similar kind of stuff, in my previous post Hack the standard function in library and call the native library function afterwards .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top