Merge remote-tracking branch 'lp-anj7/expanded-rules' into 7.0
* lp-anj7/expanded-rules: Generate module version files with new RULES_EXPAND facilities Extend RULES_EXPAND to add more features More generator doc updates Document <library>_API = <stem> for Makefiles Convert epicsShareAPI to epicsStdCall in modules/ca Update generator script Modify rules to allow multiple API.h libraries to be built Convert modules/ca to use LIBCA_API instead of epicsShare Try out a representative sample of APIs from multiple libraries Add build rules to generate and install *API.h header files Add script to generate *API.h headers
This commit is contained in:
@@ -31,6 +31,7 @@ PERL_SCRIPTS += epicsProve.pl
|
||||
PERL_SCRIPTS += expandVars.pl
|
||||
PERL_SCRIPTS += fullPathName.pl
|
||||
PERL_SCRIPTS += installEpics.pl
|
||||
PERL_SCRIPTS += makeAPIheader.pl
|
||||
PERL_SCRIPTS += makeMakefile.pl
|
||||
PERL_SCRIPTS += makeTestfile.pl
|
||||
PERL_SCRIPTS += mkmf.pl
|
||||
@@ -50,6 +51,7 @@ HTMLS += EPICS/Getopts.html
|
||||
HTMLS += EPICS/Path.html
|
||||
HTMLS += EPICS/Readfile.html
|
||||
HTMLS += fullPathName.html
|
||||
HTMLS += makeAPIheader.html
|
||||
HTMLS += munch.html
|
||||
HTMLS += podToHtml.html
|
||||
HTMLS += podRemove.html
|
||||
|
||||
175
src/tools/makeAPIheader.pl
Normal file
175
src/tools/makeAPIheader.pl
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/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 symbols import/export
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<makeAPIheader.pl> [B<-h>] [B<-o> path/fileB<API.h>] stem
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Creates a C/C++ header file containing macro definitions for C<STEM_API> and
|
||||
C<epicsStdCall> which on Windows will expand to the appropriate C<__declspec>
|
||||
and C<__stdcall> keywords respectively, and on GCC to a C<visibility>
|
||||
attribute and nothing.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
B<makeAPIheader.pl> understands the following options:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-h>
|
||||
|
||||
Help, display this document as text.
|
||||
|
||||
=item B<-o> path/fileB<API.h>
|
||||
|
||||
Pathname to the output file to be created. Must end with C<API.h>.
|
||||
|
||||
=back
|
||||
|
||||
If no output filename is set, the name will be generated by appending
|
||||
C<API.h> to the I<stem> argument.
|
||||
|
||||
The I<stem> used must be a legal C identifier, starting with a letter or
|
||||
underscore followed by any combination of digits, letters and underscores.
|
||||
|
||||
=head1 PURPOSE
|
||||
|
||||
The generated header and the macros in it replace the C<epicsShare> macros
|
||||
that were defined in the C<shareLib.h> header, avoiding the need for shared
|
||||
library implementation code to define the C<epicsExportSharedSymbols> macro in
|
||||
between the import and export headers. The order of including header files no
|
||||
longer matters when using this approach.
|
||||
|
||||
For libraries that contain EPICS record, device, driver or link support and use
|
||||
the epicsExport.h macros to publish the associated support entry table for the
|
||||
IOC to locate, switching from shareLib.h to a generated API header file is not
|
||||
recommended. The old approach is simpler in these cases.
|
||||
|
||||
=head1 USING WITH EPICS
|
||||
|
||||
In a Makefile that is building a DLL or shared library, set the variable
|
||||
C<API_HEADER> to the name of the API header file to be generated. This name
|
||||
must start with a legal C identifier and end with C<API.h>. The C identifier
|
||||
part preceeding the C<API.h> is referred to here as the I<stem> for this
|
||||
header file, and should be a short name in lower case or camelCase. For
|
||||
example the stem used in the example here is C<libCom>:
|
||||
|
||||
# Generate our library API header file
|
||||
API_HEADER += libComAPI.h
|
||||
|
||||
The Makefile also needs to find the API stem given the name of the library.
|
||||
These may be different, as shown in our example since the libCom API actually
|
||||
gets used by a library whose formal name is just "Com". This relationship is
|
||||
indicated by setting the C<library_API> variable to the API stem, like this:
|
||||
|
||||
# Library to build:
|
||||
LIBRARY = Com
|
||||
# API stem for the Com library
|
||||
Com_API = libCom
|
||||
|
||||
Then in each header file that declares a function, global variable or C++
|
||||
class or method to be exported by the library, include the generated header
|
||||
file and then decorate those declarations with the all-uppercase keyword
|
||||
C<STEM_API> as in these examples:
|
||||
|
||||
LIBCOM_API void epicsExit(int status);
|
||||
LIBCOM_API int asCheckClientIP;
|
||||
class LIBCOM_API epicsTime { ... }
|
||||
LIBCOM_API virtual ~fdManager ();
|
||||
|
||||
The generated header file also defines a second macro C<epicsStdCall> which on
|
||||
Windows expands to C<__stdcall> to indicate the calling convention for this
|
||||
routine. When used, this macro should be placed between the return type and
|
||||
the routine name, like this:
|
||||
|
||||
LIBCOM_API int epicsStdCall iocshCmd(const char *cmd);
|
||||
|
||||
It is possible to build more than one shared library in the same Makefile,
|
||||
although each C or C++ source file can only be included in one library. Just
|
||||
repeat the above instructions, using different stems for each library.
|
||||
|
||||
=cut
|
||||
|
||||
our ($opt_o, $opt_h);
|
||||
|
||||
sub HELP_MESSAGE {
|
||||
pod2usage(-exitval => 2, -verbose => $opt_h ? 2 : 0);
|
||||
}
|
||||
|
||||
HELP_MESSAGE() if !getopts('ho:') || $opt_h || @ARGV != 1;
|
||||
|
||||
my $stem = shift @ARGV;
|
||||
die "makeAPIheader.pl: API stem '$stem' is not a legal C identifier\n"
|
||||
unless $stem =~ m/^ [A-Za-z_][0-9A-Za-z_]* $/x;
|
||||
|
||||
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__)
|
||||
|
||||
# if !defined(epicsStdCall)
|
||||
# define epicsStdCall __stdcall
|
||||
# endif
|
||||
|
||||
# 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(epicsStdCall)
|
||||
# define epicsStdCall
|
||||
#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
|
||||
Reference in New Issue
Block a user