Repository: conan-io/conan-center-index

Issue:
[package] libpq/*: static MinGW build
### Package and Environment Details

* Package Name/Version: **libpq/\***
* Operating System+version: **Windows 10**
* Compiler+version: **MinGW/GCC**

Commit 2f3a500 introduces a check that is supposed to prevent static builds in MinGW (later moved to the `validate()` method). But the condition for this check here tests for `options.shared == True`, so it raises an exception for building a shared library. As I understand, the opposite should be the case.

For curiosity: What is actually the reason for this limitation? I couldn't find any explanation for this in the internet.



Discussion:
https://github.com/conan-io/conan-center-index/pull/15305 should fix this issue by preventing static build if MinGW, and build shared by default with MinGW. For the reason, well all I can say is that upstream build files are doing weird things which prevent to get the static lib, either because it's overridden by import lib of dll or some other weirdness.

I've found:
https://www.postgresql.org/message-id/CABFfbXvONEKE2Bpnbfm5=f3fVVLpv6jLVUAhF7iGoWN7a_EeRw@mail.gmail.com

Resolving patch:
diff --git a/recipes/libpq/all/conanfile.py b/recipes/libpq/all/conanfile.py
--- a/recipes/libpq/all/conanfile.py
+++ b/recipes/libpq/all/conanfile.py
@@ -1,5 +1,4 @@
 from conan import ConanFile
-from conan.errors import ConanInvalidConfiguration
 from conan.tools.apple import fix_apple_shared_install_name
 from conan.tools.build import cross_building
 from conan.tools.env import Environment, VirtualBuildEnv, VirtualRunEnv
@@ -36,10 +35,6 @@ class LibpqConan(ConanFile):
         "disable_rpath": False,
     }
 
-    @property
-    def _is_mingw(self):
-        return self.settings.os == "Windows" and self.settings.compiler == "gcc"
-
     @property
     def _is_clang8_x86(self):
         return self.settings.os == "Linux" and \
@@ -58,9 +53,6 @@ def config_options(self):
         if self.settings.os == "Windows":
             self.options.rm_safe("fPIC")
             self.options.rm_safe("disable_rpath")
-        if self._is_mingw:
-            # TODO: back to static by default once mingw static fixed
-            self.options.shared = True
 
     def configure(self):
         if self.options.shared:
@@ -75,11 +67,6 @@ def requirements(self):
         if self.options.with_openssl:
             self.requires("openssl/1.1.1s")
 
-    def validate(self):
-        if self._is_mingw and not self.options.shared:
-            # FIXME: Seems like static lib is not created or is overridden at build time by import lib of dll
-            raise ConanInvalidConfiguration("static mingw build is not possible")
-
     def build_requirements(self):
         if is_msvc(self):
             self.tool_requires("strawberryperl/5.32.1.1")
@@ -163,6 +150,12 @@ def _patch_sources(self):
                 replace_in_file(self,config_default_pl,
                                       "openssl   => undef",
                                       "openssl   => '%s'" % openssl.package_folder.replace("\\", "/"))
+        elif self.settings.os == "Windows":
+            if self.settings.get_safe("compiler.threads") == "posix":
+                # Use MinGW pthread library
+                replace_in_file(self, os.path.join(self.source_folder, "src", "interfaces", "libpq", "Makefile"),
+                "ifeq ($(enable_thread_safety), yes)\nOBJS += pthread-win32.o\nendif",
+                "")
 
     def build(self):
         apply_conandata_patches(self)
@@ -196,10 +189,11 @@ def _remove_unused_libraries_from_package(self):
         rm(self, "*.dll", lib_folder)
         if self.options.shared:
             for lib in glob.glob(os.path.join(lib_folder, "*.a")):
-                if not (self.settings.os == "Windows" and os.path.basename(lib) == "libpq.a"):
+                if not (self.settings.os == "Windows" and os.path.basename(lib) == "libpq.dll.a"):
                     os.remove(lib)
         else:
             rm(self, "*.dll", bin_folder)
+            rm(self, "*.dll.a", lib_folder)
             rm(self, "*.so*", lib_folder)
             rm(self, "*.dylib", lib_folder)
 
@@ -270,6 +264,8 @@ def package_info(self):
                 if Version(self.version) >= "12":
                     self.cpp_info.components["pgcommon"].libs.append("pgcommon_shlib")
                     self.cpp_info.components["pgport"].libs = ["pgport", "pgport_shlib"]
+                    if self.settings.os == "Windows":
+                        self.cpp_info.components["pgport"].system_libs = ["ws2_32"]
                     self.cpp_info.components["pgcommon"].requires.append("pgport")
 
         if self.settings.os in ["Linux", "FreeBSD"]:


Test patch:
diff --git a/recipes/libpq/all/test_package/test_package.c b/recipes/libpq/all/test_package/test_package.c
--- a/recipes/libpq/all/test_package/test_package.c
+++ b/recipes/libpq/all/test_package/test_package.c
@@ -11,7 +11,7 @@ int main() {
 
     conn = PQconnectdb("dbname = postgres");
     PQstatus(conn);
-    
+
     PQfinish(conn);
     return EXIT_SUCCESS;
 }