From 017d561b8d95bc207885bf2b86e51b5497c4a3b7 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 10 Mar 2020 23:41:15 -0500 Subject: [PATCH] Update generator script Rename xxxSTD_API to epicsStdCall, don't redefine. Ensure name stem is a legal C identifier. Update the Pod text --- src/tools/makeAPIheader.pl | 87 +++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/src/tools/makeAPIheader.pl b/src/tools/makeAPIheader.pl index 79965a615..cb7fde97d 100644 --- a/src/tools/makeAPIheader.pl +++ b/src/tools/makeAPIheader.pl @@ -10,17 +10,18 @@ use Pod::Usage; =head1 NAME -makeAPIheader.pl - Create a header for marking API import/export +makeAPIheader.pl - Create a header for marking API symbols import/export =head1 SYNOPSIS -B [B<-h>] [B<-o> fileAPI.h] stem +B [B<-h>] [B<-o> path/fileB] stem =head1 DESCRIPTION Creates a C/C++ header file containing macro definitions for C and -C which on Windows will expand to the appropriate C<__declspec> -and C<__stdcall> keywords and under GCC to a C attribute. +C which on Windows will expand to the appropriate C<__declspec> +and C<__stdcall> keywords respectively, and on GCC to a C +attribute and nothing. =head1 OPTIONS @@ -32,58 +33,81 @@ B understands the following options: Help, display this document as text. -=item B<-o> fileAPI.h +=item B<-o> path/fileB -Name of the output file to be created. Must end C. +Pathname to the output file to be created. Must end with C. =back -If no output filename is set, the filename will be generated by appending -C to the B argument. +If no output filename is set, the name will be generated by appending +C to the I argument. -=head1 USAGE FOR EPICS +The I used must be a legal C identifier, starting with a letter or +underscore followed by any combination of digits, letters and underscores. -In the Makefile that is building a DLL or shared library, set the variable -C to the name of the name of the header file to be generated, -which must end with C. The part before that is referred to as the -I for this library. For example the stem here is C: +=head1 PURPOSE + +The generated header and the macros in it replace the C macros +that were defined in the C header, avoiding the need for shared +library implementation code to define the C macro in +between the import and export headers. The order of including header files no +longer matters when using this approach. + +=head1 USING WITH EPICS + +In a Makefile that is building a DLL or shared library, set the variable +C to the name of the API header file to be generated. This name +must start with a legal C identifier and end with C. The C identifier +part preceeding the C is referred to here as the I 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: # Generate our library API header file - API_HEADER = libComAPI.h + 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: +says C), add another line like this: # Set the API Building flag while we are building the code - $(LIBNAME) $(SHRLIBNAME): USR_CPPFLAGS += -DLIBCOM_API_BUILDING + $(LIBNAME) $(SHRLIBNAME): USR_CPPFLAGS += -DBUILDING_libCom_API -Replace the string C above with the upper-case version of the stem -that you used in your header filename. +For your library replace the string C in the last word above with +the stem from 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 like this: +Then in each header file that declares a function, global variable or C++ +class or method to be exported by the library, decorate those declarations +with the all-uppercase keyword C as in these examples: LIBCOM_API void epicsExit(int status); + LIBCOM_API int asCheckClientIP; + class LIBCOM_API epicsTime { ... } + LIBCOM_API virtual ~fdManager (); -The header also defines a second macro C 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: +The generated header file also defines a second macro C 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 LIBCOMSTD_API iocshCmd(const char *cmd); + 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); + 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" @@ -102,7 +126,10 @@ print $o <<"__EOF__"; #define $guard #if defined(_WIN32) || defined(__CYGWIN__) -# define ${STEM}STD_API __stdcall + +# if !defined(epicsStdCall) +# define epicsStdCall __stdcall +# endif # if defined(BUILDING_${stem}_API) && defined(EPICS_BUILD_DLL) /* Building library as dll */ @@ -120,8 +147,8 @@ print $o <<"__EOF__"; # define ${STEM}_API #endif -#if !defined(${STEM}STD_API) -# define ${STEM}STD_API +#if !defined(epicsStdCall) +# define epicsStdCall #endif #endif /* $guard */