Add script to generate *API.h headers

This commit is contained in:
Andrew Johnson
2020-03-03 00:58:48 -06:00
parent 3871f89dcd
commit eaee851a2d
2 changed files with 143 additions and 0 deletions

141
src/tools/makeAPIheader.pl Normal file
View File

@@ -0,0 +1,141 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Std;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
use Pod::Usage;
=head1 NAME
makeAPIheader.pl - Create a header for marking API import/export
=head1 SYNOPSIS
B<makeAPIheader.pl> [B<-h>] [B<-o> fileAPI.h] stem
=head1 DESCRIPTION
Creates a C/C++ header file containing macro definitions for C<STEM_API> and
C<STEMSTD_API> which on Windows will expand to the appropriate C<__declspec>
and C<__stdcall> keywords and under GCC to a C<visibility> attribute.
=head1 OPTIONS
B<makeAPIheader.pl> understands the following options:
=over 4
=item B<-h>
Help, display this document as text.
=item B<-o> fileAPI.h
Name of the output file to be created. Must end C<API.h>.
=back
If no output filename is set, the filename will be generated by appending
C<API.h> to the B<stem> argument.
=head1 USAGE FOR EPICS
In the Makefile that is building a DLL or shared library, set the variable
C<API_HEADER> to the name of the name of the header file to be generated,
which must end with C<API.h>. The part before that is referred to as the
I<stem> for this library. For example the stem here is C<libCom>:
# Generate our library API header file
API_HEADER = libComAPI.h
Lower down in the RULES section of the same Makefile (below the line that
includes the C<$(TOP)/configure/RULES> file), add a line like this:
# Set the API Building flag while we are building the code
$(LIBNAME) $(SHRLIBNAME): USR_CPPFLAGS += -DLIBCOM_API_BUILDING
Replace the string C<LIBCOM> above with the upper-case version of the stem
that you used in your header filename.
Then in each header and source file that declares or defines a routine to be
exported by the library, decorate the routine declaration or definition with
the keyword C<STEM_API> like this:
LIBCOM_API void epicsExit(int status);
The header also defines a second macro C<STEMSTD_API> which is for Windows
builds to indicate that the calling convention for this routine must be
C<__stdcall>. If needed, this macro should be placed between the return type
and the routine name, like this:
LIBCOM_API int LIBCOMSTD_API iocshCmd(const char *cmd);
=cut
our ($opt_o, $opt_h);
sub HELP_MESSAGE {
pod2usage(-exitval => 2, -verbose => $opt_h);
}
HELP_MESSAGE() if !getopts('ho:') || $opt_h || @ARGV != 1;
my $stem = shift @ARGV;
my $outfile = defined($opt_o) ? $opt_o : "${stem}API.h";
die "makeAPIheader.pl: Output filename must end with 'API.h'\n"
unless $outfile =~ m/API\.h$/;
my $STEM = uc $stem;
my $guard = "INC_${stem}API_H";
open my $o, '>', $outfile or
die "makeAPIheader.pl: Can't create $outfile: $!\n";
print $o <<"__EOF__";
/* This is a generated file, do not edit! */
#ifndef $guard
#define $guard
#if defined(_WIN32) || defined(__CYGWIN__)
# define ${STEM}STD_API __stdcall
# if defined(BUILDING_${stem}_API) && defined(EPICS_BUILD_DLL)
/* Building library as dll */
# define ${STEM}_API __declspec(dllexport)
# elif !defined(BUILDING_${stem}_API) && defined(EPICS_CALL_DLL)
/* Calling library in dll form */
# define ${STEM}_API __declspec(dllimport)
# endif
#elif __GNUC__ >= 4
# define ${STEM}_API __attribute__ ((visibility("default")))
#endif
#if !defined(${STEM}_API)
# define ${STEM}_API
#endif
#if !defined(${STEM}STD_API)
# define ${STEM}STD_API
#endif
#endif /* $guard */
__EOF__
close $o;
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2020 UChicago Argonne LLC, as Operator of Argonne National
Laboratory.
This software is distributed under the terms of the EPICS Open License.
=cut