Repository: conan-io/conan-center-index

Issue:
[package] crashpad/cci.20210507: Missing symbols for 'crashpad::CrashReportDatabase'
Related to #5511

This symbol should be in `client.lib`, so not sure what went wrong in the recipe. Wrong linking order? Bug in the library?

### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **crashpad/cci.20210507**
  * Operating System+version: **Windows 10**
  * Compiler+version: **Visual Studio 2019 (16.9.1)**
  * Conan version: **conan 1.34.1**
  * Python version: **Python 3.7.9**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
Configuration:
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Debug/Release
compiler=Visual Studio
compiler.runtime=MTd/MT
compiler.version=16
os=Windows
os_build=Windows
```


### Steps to reproduce (Include if Applicable)
Add the following line to the recipe example:
`auto database = crashpad::CrashReportDatabase::Initialize(reportsPath)`

### Logs (Include/Attach if Applicable)
<details><summary>Click to expand log</summary>

```
error LNK2019: unresolved external symbol "public: static class std::unique_ptr<class crashpad::CrashReportDatabase,struct std::default_delete<class crashpad::CrashReportDatabase> > __cdecl crashpad::CrashReportDatabase::Initialize(class base::FilePath const &)" (?Initialize@CrashReportDatabase@crashpad@@SA?AV?$unique_ptr@VCrashReportDatabase@crashpad@@U?$default_delete@VCrashReportDatabase@crashpad@@@std@@@std@@AEBVFilePath@base@@@Z)
```

</details>



Discussion:
Adding:
```c++
#include "client/crash_report_database.h"
```
and
```
   auto database = crashpad::CrashReportDatabase::Initialize(base::FilePath("/tmp/some_path"));
```
seems to work on Linux gcc-11.

I haven't tested yet on msvc.
@madebr 
Doing the same changes you mentioned above (but just passing the `db` var as input to creator function) and running:
`conan create all crashpad/cci.20210507@test/test -s compiler="Visual Studio" -s compiler.version=16 -s compiler.runtime=MT`

I get the same error as in the description:
```
test_package.obj : error LNK2019: unresolved external symbol "public: static class std::unique_ptr<class crashpad::CrashReportDatabase,struct std::default
_delete<class crashpad::CrashReportDatabase> > __cdecl crashpad::CrashReportDatabase::Initialize(class base::FilePath const &)" (?Initialize@CrashReportDa
tabase@crashpad@@SA?AV?$unique_ptr@VCrashReportDatabase@crashpad@@U?$default_delete@VCrashReportDatabase@crashpad@@@std@@@std@@AEBVFilePath@base@@@Z) refe
renced in function "bool __cdecl startCrashpad(class base::FilePath const &,class base::FilePath const &)" (?startCrashpad@@YA_NAEBVFilePath@base@@0@Z) [C
:\repos\conan-center-index\recipes\crashpad\all\test_package\build\8acfa7f6642e42a872d24f9595f71a4c0d0a89de\test_package.vcxproj]
C:\repos\conan-center-index\recipes\crashpad\all\test_package\build\8acfa7f6642e42a872d24f9595f71a4c0d0a89de\bin\test_package.exe : fatal error LNK1120: 1
 unresolved externals [C:\repos\conan-center-index\recipes\crashpad\all\test_package\build\8acfa7f6642e42a872d24f9595f71a4c0d0a89de\test_package.vcxproj]
ERROR: crashpad/cci.20210507@test/test (test package): Error in build() method, line 12
        cmake.build()
        ConanException: Error 1 while executing cmake --build C:\repos\conan-center-index\recipes\crashpad\all\test_package\build\8acfa7f6642e42a872d24f9595f71a4c0d0a89de --config Release -- /m:20 /verbosity:minimal
```

Resolving patch:
diff --git a/recipes/crashpad/all/conanfile.py b/recipes/crashpad/all/conanfile.py
--- a/recipes/crashpad/all/conanfile.py
+++ b/recipes/crashpad/all/conanfile.py
@@ -191,6 +191,14 @@ def build(self):
                     targets=" ".join(targets),
                     parallel=tools.cpu_count()), run_environment=True)
 
+        def lib_filename(name):
+            prefix, suffix = ("", ".lib")  if self.settings.compiler == "Visual Studio" else ("lib", ".a")
+            return "{}{}{}".format(prefix, name, suffix)
+        tools.rename(os.path.join(self._source_subfolder, "out", "Default", "obj", "client", lib_filename("common")),
+                     os.path.join(self._source_subfolder, "out", "Default", "obj", "client", lib_filename("client_common")))
+        tools.rename(os.path.join(self._source_subfolder, "out", "Default", "obj", "handler", lib_filename("common")),
+                     os.path.join(self._source_subfolder, "out", "Default", "obj", "handler", lib_filename("handler_common")))
+
     def package(self):
         self.copy("LICENSE", src=self._source_subfolder, dst="licenses")
 
@@ -201,10 +209,14 @@ def package(self):
         self.copy("*.h", src=os.path.join(self._source_subfolder, "out", "Default", "gen", "build"), dst=os.path.join("include", "build"))
 
         self.copy("*.a", src=os.path.join(self._source_subfolder, "out", "Default"), dst="lib", keep_path=False)
+
         self.copy("*.lib", src=os.path.join(self._source_subfolder, "out", "Default"), dst="lib", keep_path=False)
         self.copy("crashpad_handler", src=os.path.join(self._source_subfolder, "out", "Default"), dst="bin", keep_path=False)
         self.copy("crashpad_handler.exe", src=os.path.join(self._source_subfolder, "out", "Default"), dst="bin", keep_path=False)
         self.copy("crashpad_handler_com.com", src=os.path.join(self._source_subfolder, "out", "Default"), dst="bin", keep_path=False)
+        if self.settings.os == "Windows":
+            tools.rename(os.path.join(self.package_folder, "bin", "crashpad_handler_com.com"),
+                         os.path.join(self.package_folder, "bin", "crashpad_handler.com"))
 
         # Remove accidentally copied libraries. These are used by the executables, not by the libraries.
         tools.remove_files_by_mask(os.path.join(self.package_folder, "lib"), "*getopt*")
@@ -243,11 +255,11 @@ def package_info(self):
             self.cpp_info.components["util"].frameworks.extend(["CoreFoundation", "Foundation", "IOKit"])
             self.cpp_info.components["util"].system_libs.append("bsm")
 
-        self.cpp_info.components["common"].libs = ["common"]
-        self.cpp_info.components["common"].requires = ["util"]
+        self.cpp_info.components["client_common"].libs = ["client_common"]
+        self.cpp_info.components["client_common"].requires = ["util", "mini_chromium_base"]
 
         self.cpp_info.components["client"].libs = ["client"]
-        self.cpp_info.components["client"].requires = ["common"]
+        self.cpp_info.components["client"].requires = ["util", "mini_chromium_base", "client_common"]
         if self.settings.os == "Windows":
             self.cpp_info.components["client"].system_libs.append("rpcrt4")
 
@@ -255,7 +267,7 @@ def package_info(self):
         self.cpp_info.components["context"].requires = ["util"]
 
         self.cpp_info.components["snapshot"].libs = ["snapshot"]
-        self.cpp_info.components["snapshot"].requires = ["common", "mini_chromium_base", "util"]
+        self.cpp_info.components["snapshot"].requires = ["client_common", "mini_chromium_base", "util"]
         if tools.is_apple_os(self.settings.os):
             self.cpp_info.components["snapshot"].frameworks.extend(["OpenCL"])
 
@@ -265,8 +277,11 @@ def package_info(self):
         self.cpp_info.components["minidump"].libs = ["minidump"]
         self.cpp_info.components["minidump"].requires = ["snapshot", "mini_chromium_base", "util"]
 
+        self.cpp_info.components["handler_common"].libs = ["handler_common"]
+        self.cpp_info.components["handler_common"].requires = ["client_common", "snapshot", "util"]
+
         self.cpp_info.components["handler"].libs = ["handler"]
-        self.cpp_info.components["handler"].requires = ["common", "minidump", "snapshot"]
+        self.cpp_info.components["handler"].requires = ["client", "util", "handler_common", "minidump", "snapshot"]
 
         bin_path = os.path.join(self.package_folder, "bin")
         self.output.info("Appending PATH environment variable: {}".format(bin_path))


Test patch:
diff --git a/recipes/crashpad/all/test_package/conanfile.py b/recipes/crashpad/all/test_package/conanfile.py
--- a/recipes/crashpad/all/test_package/conanfile.py
+++ b/recipes/crashpad/all/test_package/conanfile.py
@@ -20,6 +20,6 @@ def test(self):
             handler_bin_path = os.path.join(self.deps_cpp_info["crashpad"].rootpath, "bin", handler_exe)
             self.run("%s %s/db %s" % (bin_path, test_env_dir, handler_bin_path), run_environment=True)
             if self.settings.os == "Windows":
-                handler_exe = "crashpad_handler_com.com"
+                handler_exe = "crashpad_handler.com"
                 handler_bin_path = os.path.join(self.deps_cpp_info["crashpad"].rootpath, "bin", handler_exe)
                 self.run("%s %s/db %s" % (bin_path, test_env_dir, handler_bin_path), run_environment=True)
diff --git a/recipes/crashpad/all/test_package/test_package.cpp b/recipes/crashpad/all/test_package/test_package.cpp
--- a/recipes/crashpad/all/test_package/test_package.cpp
+++ b/recipes/crashpad/all/test_package/test_package.cpp
@@ -9,6 +9,8 @@
 #include "client/crashpad_client.h"
 #include "client/settings.h"
 
+#include "client/crash_report_database.h"
+
 bool startCrashpad(const base::FilePath &db,
                    const base::FilePath &handler) {
     std::string              url("http://localhost");
@@ -44,5 +46,9 @@ int main(int argc, char* argv[]) {
     base::FilePath handler(argv[2]);
 #endif
 
+    // Test availability of this function.
+    auto database = crashpad::CrashReportDatabase::Initialize(db);
+    (void) database; /* Avoid warning about unused variable */
+
     return startCrashpad(db, handler) ? 0 : 1;
 }