Link with .def files
authorTanzinul Islam <tanzinul.islam@gmail.com>
Sun, 13 Dec 2020 18:01:46 +0000 (18:01 +0000)
committerDmitry Belyavskiy <beldmit@gmail.com>
Mon, 19 Apr 2021 09:05:55 +0000 (11:05 +0200)
MSVC's `link.exe` automatically finds `__cdecl` C functions (which are
decorated with a leading underscore by the compiler) when they are
mentioned in a `.def` file without the leading underscore.  This is an
[under-documented feature][1] of MSVC's `link.exe`.  C++Builder's
`ilink32.exe` doesn't do this, and thus needs the name-translation in
the `.def` file.  Then `implib.exe` needs to be told to re-add it.

(The Clang-based `bcc32c.exe` doesn't implement the [`-vu` or `-u-`][2]
options to skip adding the leading underscore to `__cdecl` C function
names, so this is the only way to have things work with non-underscored
export names in the DLLs.)

[1]: https://github.com/MicrosoftDocs/cpp-docs/issues/2653
[2]: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Options_Not_Supported_by_Clang-enhanced_C%2B%2B_Compilers#BCC32_Options_that_Are_Not_Supported_by_Clang-enhanced_C.2B.2B_Compilers

Also silence linker warnings on duplicate symbols and ensure that error-
case cleanup in link rules work in C++Builder's `make.exe`.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/13540)

Configurations/50-cppbuilder.conf
Configurations/platform/Windows/cppbuilder.pm [new file with mode: 0644]
Configurations/windows-makefile.tmpl
util/mkdef.pl

index 7ca972956a48a2774c00f09241f6edbd5f7d8458..b604e12d09c315c2e24aa300a50a172fc6e3e896 100644 (file)
@@ -20,12 +20,12 @@ my %targets = (
         coutflag         => "-o",
         cpp_depend_flags => "-Hp",
         LD               => "ilink32",
-        LDFLAGS          => picker(default => "-ap -x -Gn -q",
+        LDFLAGS          => picker(default => "-x -Gn -q -w-dup",
                                    debug   => '-j"$(BDS)\lib\win32c\debug" ' .
                                               '-L"$(BDS)\lib\win32c\debug" -v',
                                    release => '-j"$(BDS)\lib\win32c\release" ' .
                                               '-L"$(BDS)\lib\win32c\release"'),
-        bin_lflags       => "-Tpe c0x32.obj wildargs.obj",
+        bin_lflags       => "-ap -Tpe c0x32.obj wildargs.obj",
         ldoutflag        => ",",
         ldpostoutflag    => ",,",
         ld_resp_delim    => " +\n",
@@ -44,11 +44,12 @@ my %targets = (
         RCFLAGS          => '-i"$(BDS)\include\windows\sdk"',
         rcoutflag        => "-fo",
         shared_target    => "win-shared",
-        shared_ldflag    => "-Tpd c0d32.obj",
-        dso_lflags       => "-Tpd c0d32.obj",
+        shared_ldflag    => "-aa -Tpd c0d32.obj",
         lddefflag        => ",",
         ldresflag        => ",",
-        ld_implib_rule   => 'implib $< $**',
+        ld_implib_rule   => 'implib -a $< $**',
         dso_scheme       => "win32",
+        shared_defflag   => '',
+        perl_platform    => 'Windows::cppbuilder',
     }
 );
diff --git a/Configurations/platform/Windows/cppbuilder.pm b/Configurations/platform/Windows/cppbuilder.pm
new file mode 100644 (file)
index 0000000..b4d208d
--- /dev/null
@@ -0,0 +1,16 @@
+package platform::Windows::cppbuilder;
+
+use vars qw(@ISA);
+
+require platform::Windows::MSVC;
+@ISA = qw(platform::Windows::MSVC);
+
+sub pdbext              { '.tds' }
+
+# C++Builder's Clang-based compilers prepend an underscore to __cdecl-convention
+# C functions, and the linker needs those as the InternalName in the .def file.
+sub export2internal {
+    return "_$_[1]";
+}
+
+1;
index bcb092d045b6d9f493db6dd1d99765965f7bb1bc..6ceab7e94d5c4dbc3f0dfe051aaaf01a89f3f74f 100644 (file)
@@ -878,7 +878,7 @@ $import: $dll
 $dll: $deps
        IF EXIST $full.manifest DEL /F /Q $full.manifest
        IF EXIST \$@ DEL /F /Q \$@
-       \$(LD) \$(LDFLAGS) \$(LIB_LDFLAGS) @<< $implib_flag || (DEL /Q \$(\@B).* $import; EXIT 1)
+       cmd /C "\$(LD) \$(LDFLAGS) \$(LIB_LDFLAGS) @<< $implib_flag || (DEL /Q \$(\@B).* $import & EXIT 1)"
 $objs$target{ld_resp_delim}\$(LDOUTFLAG)$dll$target{ldpostoutflag}$target{ld_resp_delim}$linklibs\$(LIB_EX_LIBS)$target{ld_resp_delim}$shared_def$target{ldresflag}$ress
 <<
        IF EXIST $dll.manifest \\
@@ -914,7 +914,7 @@ EOF
      return <<"EOF";
 $dso: $deps
        IF EXIST $dso.manifest DEL /F /Q $dso.manifest
-       \$(LD) \$(LDFLAGS) \$(DSO_LDFLAGS) @<< || (DEL /Q \$(\@B).* $dso_n.*; EXIT 1)
+       cmd /C "\$(LD) \$(LDFLAGS) \$(DSO_LDFLAGS) @<< || (DEL /Q \$(\@B).* $dso_n.* & EXIT 1)"
 $objs$target{ld_resp_delim}\$(LDOUTFLAG)$dso$target{ldpostoutflag}$target{ld_resp_delim}$linklibs \$(DSO_EX_LIBS)$target{ld_resp_delim}$shared_def$target{ldresflag}$ress
 <<
        IF EXIST $dso.manifest \\
index a4772e9c8f033ed8a87db9bd785872bfe2bb1439..3207040e257ef428acd97912a50238e4a477b699 100755 (executable)
@@ -295,12 +295,16 @@ sub writer_windows {
 ; Definition file for the DLL version of the $libname library from OpenSSL
 ;
 
-LIBRARY         $libname
+LIBRARY         "$libname"
 
 EXPORTS
 _____
     for (@_) {
-        print "    ",$_->name(),"\n";
+        print "    ",$_->name();
+        if (platform->can('export2internal')) {
+            print "=". platform->export2internal($_->name());
+        }
+        print "\n";
     }
 }