git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Rationale behind 'extern' on protypes in .h files
@ 2013-12-22 15:51 Ravi Shekhar Jethani
  2013-12-22 17:11 ` Stefan Beller
  0 siblings, 1 reply; 5+ messages in thread
From: Ravi Shekhar Jethani @ 2013-12-22 15:51 UTC (permalink / raw)
  To: git

Hi,
I am a C & Data Structure teacher at at an institute. Up until now I
have only written classroom type C code. I always had interest in
operating systems especially Linux Kernel but never got into anything
just passively followed 'lwn.net', 'dr dobbs magazine' etc.

But the series '30 Linux Kernel Developers in 30 Weeks' on 'linux.com'
has really pushed me over the edge and  I have this new found interest
towards Linux and C. As these articles suggest that I should have a
good experience in user space before I can even touch the kernel. So
to get a feel of how actual real world C projects look like I have
taken two excellent projects as my reference 'Git' and 'libvirt'. Also
'Linux Formrnal Scratch' to get started towards Linux internals.

Although I have a good understanding of the basic/advanced concepts
like pointers, memory management etc but many concepts like good error
handling mechanism, unit testing, build systems etc. were always
blurry but I know that this is just a start towards a long journey
towards Linux Kernel.


Now, my real question :
1) I cannot understand the reason behind making function prototypes as
extern. What purpose does this serve? AFAIK we put definition in a .c
file and the prototype in a .h thats it.

2) Why are some  prototypes in some of the .h file are extern and
others are not?

Thank you guys for reading through. Any suggestions are humbly welcome.
Ravi S. Jethani

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Rationale behind 'extern' on protypes in .h files
  2013-12-22 15:51 Rationale behind 'extern' on protypes in .h files Ravi Shekhar Jethani
@ 2013-12-22 17:11 ` Stefan Beller
  2013-12-22 18:26   ` Jed Brown
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Beller @ 2013-12-22 17:11 UTC (permalink / raw)
  To: Ravi Shekhar Jethani, git

On 22.12.2013 16:51, Ravi Shekhar Jethani wrote:

> 
> Now, my real question :
> 1) I cannot understand the reason behind making function prototypes as
> extern. What purpose does this serve? AFAIK we put definition in a .c
> file and the prototype in a .h thats it.
> 
> 2) Why are some  prototypes in some of the .h file are extern and
> others are not?
> 
> Thank you guys for reading through. Any suggestions are humbly welcome.
> Ravi S. Jethani
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

That's an interesting question. From my understanding there is no
difference for functions declarations being set to extern or not,
because extern is the default on functions. It is however important
for variables to mark them extern if they're in a header file.

After a quick research on the web, it may be there for historical
reasons. Back then, when there were one pass compilers,
the compiler needed to know where the function is to be found.
(extern was not default at these times?)

Another reason I could make up, would be to indicate,
whether the function is in the c file having the
same name as the header file.
For example in builtin.h there are all the functions declared
extern, as the implementation of the functions are found in
builtin/*.c
In another header cache-tree.h there are function declarations
without explicit extern keyword, and the implementation
is found in the cache-tree.c file (${SAME-NAME-AS-HEADER}.C)
This is however not always the case as found in archive.{c,h}

I'd be also interested in knowing the real reason for this rationale.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Rationale behind 'extern' on protypes in .h files
  2013-12-22 17:11 ` Stefan Beller
@ 2013-12-22 18:26   ` Jed Brown
  2013-12-23 15:24     ` Ravi Shekhar Jethani
  0 siblings, 1 reply; 5+ messages in thread
From: Jed Brown @ 2013-12-22 18:26 UTC (permalink / raw)
  To: Stefan Beller, Ravi Shekhar Jethani, git

[-- Attachment #1: Type: text/plain, Size: 861 bytes --]

Stefan Beller <stefanbeller@googlemail.com> writes:
> From my understanding there is no
> difference for functions declarations being set to extern or not,
> because extern is the default on functions.

There is a difference for shared libraries if you would like to control
which symbols are exported.  With gcc, for example, you might compile
using -fvisibility=hidden.  Any functions explicitly declared with
extern, bearing __attribute__((visibility("default")), or using
visibility pragmas will be exported (similar to __declspec(dllexport) on
Windows).  Other functions will be internal to the shared library so you
don't have to worry about callers depending on those symbols and
performance can be a bit better by skipping the PLT and avoiding symbol
relocations at load time.  See Drepper's guide for more.

http://www.akkadia.org/drepper/dsohowto.pdf

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Rationale behind 'extern' on protypes in .h files
  2013-12-22 18:26   ` Jed Brown
@ 2013-12-23 15:24     ` Ravi Shekhar Jethani
  2013-12-23 16:59       ` Jed Brown
  0 siblings, 1 reply; 5+ messages in thread
From: Ravi Shekhar Jethani @ 2013-12-23 15:24 UTC (permalink / raw)
  To: Jed Brown; +Cc: Stefan Beller, git

2013/12/22 Jed Brown <jed@59a2.org>:
> There is a difference for shared libraries if you would like to control
> which symbols are exported.  With gcc, for example, you might compile
> using -fvisibility=hidden.  Any functions explicitly declared with
> extern, bearing __attribute__((visibility("default")), or using
> visibility pragmas will be exported (similar to __declspec(dllexport) on
> Windows).  Other functions will be internal to the shared library so you
> don't have to worry about callers depending on those symbols and
> performance can be a bit better by skipping the PLT and avoiding symbol
> relocations at load time.  See Drepper's guide for more.
>
> http://www.akkadia.org/drepper/dsohowto.pdf

To check this I installed the libgit2-dev package which installed:
/usr/include/git2/*.h , /usr/lib/libgit2.so
Now, I exported all symbols using:
$ readelf -s /usr/lib/libgit2.so
and tried to match these with 'externed' prototypes in the Git source
directory..no matches.
I am confused!!!.

Also I checked this:
$ ldd git
There is no 'gitish' .so in the output; it seems everything is packed
inside one executable.
So your second point 'skipping the PLT...' also doesn't seem to apply here.


Regards,
Ravi Shekhar Jethani

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Rationale behind 'extern' on protypes in .h files
  2013-12-23 15:24     ` Ravi Shekhar Jethani
@ 2013-12-23 16:59       ` Jed Brown
  0 siblings, 0 replies; 5+ messages in thread
From: Jed Brown @ 2013-12-23 16:59 UTC (permalink / raw)
  To: Ravi Shekhar Jethani; +Cc: Stefan Beller, git

[-- Attachment #1: Type: text/plain, Size: 2202 bytes --]

Ravi Shekhar Jethani <rsjethani@gmail.com> writes:
> To check this I installed the libgit2-dev package which installed:
> /usr/include/git2/*.h , /usr/lib/libgit2.so
> Now, I exported all symbols using:
> $ readelf -s /usr/lib/libgit2.so
> and tried to match these with 'externed' prototypes in the Git source
> directory..no matches.
> I am confused!!!.

libgit2 is an entirely different package from Git.  If you look at the
libgit2 sources (https://github.com/libgit2/libgit2), look in
include/git2/common.h:

/** Declare a public function exported for application use. */
#if __GNUC__ >= 4
# define GIT_EXTERN(type) extern \
                         __attribute__((visibility("default"))) \
                         type
#elif defined(_MSC_VER)
# define GIT_EXTERN(type) __declspec(dllexport) type
#else
# define GIT_EXTERN(type) extern type
#endif


I have always used __attribute__((visibility("default"))), but the gcc
man page says

    extern declarations are not affected by -fvisibility, so a lot of
    code can be recompiled with -fvisibility=hidden with no
    modifications.  However, this means that calls to "extern" functions
    with no explicit visibility use the PLT, so it is more effective to
    use "__attribute ((visibility))" and/or "#pragma GCC visibility" to
    tell the compiler which "extern" declarations should be treated as
    hidden.

However, I don't understand what the first statement means
(documentation bug?) since -fvisibility=hidden causes functions declared
with 'extern' to be hidden.

symbols.c:
EXTERN int foo(void);
int foo(void) {return 1;}

$ gcc -fvisibility=hidden -DEXTERN=extern -shared -o libsymbols.so symbols.c
$ nm -D libsymbols.so | grep foo
$

meanwhile,

$ gcc -fvisibility=hidden -DEXTERN='__attribute((visibility("default")))' -shared -o libsymbols.so symbols.c
$ nm -D libsymbols.so | grep foo
000000000000055c T foo

> Also I checked this:
> $ ldd git
> There is no 'gitish' .so in the output; it seems everything is packed
> inside one executable.
> So your second point 'skipping the PLT...' also doesn't seem to apply here.

My comment applied to shared libraries in general, not specifically to
Git (which isn't a shared library).

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-12-23 16:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-22 15:51 Rationale behind 'extern' on protypes in .h files Ravi Shekhar Jethani
2013-12-22 17:11 ` Stefan Beller
2013-12-22 18:26   ` Jed Brown
2013-12-23 15:24     ` Ravi Shekhar Jethani
2013-12-23 16:59       ` Jed Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).