Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crashpad recipe #5511

Merged
merged 27 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
76393f9
sentry: add recipe (WIP)
madebr May 6, 2021
72e829c
switch to github fork
madebr May 7, 2021
c3c5344
crashpad: only require libcurl when curl is needed
madebr May 7, 2021
97da449
crashpad: add windows system libraries
madebr May 7, 2021
86211a0
crashpad: add explicit zlib
madebr May 7, 2021
9f80e66
crashpad: add tls option if http_transport=socket + add tls option if…
madebr May 7, 2021
c33efe3
crashpad: fixes
madebr May 7, 2021
df147bb
crashpad: various
madebr May 8, 2021
9820f33
crashpad: no Windows for you
madebr May 10, 2021
b5a2615
crashpad: print found files in library folder (DEBUG)
madebr May 10, 2021
d23d8e2
crashpad: handle libs per component
madebr May 10, 2021
1fadeea
crashpad: needs CoreFoundation framework
madebr May 10, 2021
d2d39f8
crashpad: cosmetup changes
madebr May 10, 2021
f97b718
crashpad: apple thingies
madebr May 13, 2021
ef8fd4a
crashpad: fixie
madebr May 13, 2021
7fa8a36
crashpad: fixie^2
madebr May 13, 2021
0a59692
crashpad: add ninja to build_requires
madebr May 13, 2021
5bf6525
crashpad: add components + bump git hash
madebr May 13, 2021
0fba308
crashpad: drop verbose ninja build
madebr May 13, 2021
3f7c73c
crashpad: crashpad requires c++14 (pass through CMake target)
madebr May 13, 2021
91fb3b5
crashpad: add provides attribute to recipe
madebr May 15, 2021
d173ac2
crashpad: add mini_chromium provides + add bin to PATH env
madebr May 15, 2021
eb7a82a
crashpad: build crash_handler.com on Windows
madebr May 21, 2021
38c4462
crashpad: use patches + msvc + win_helper.py -> py3
madebr May 21, 2021
d2859a5
crashpad: remove unused patch
madebr May 21, 2021
a1f3795
crashpad: update comments
madebr May 21, 2021
63a61f8
crashpad: check compiler versions in validate()
madebr May 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions recipes/crashpad/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
sources:
"cci.20210507":
url:
crashpad:
url: "https://github.com/chromium/crashpad/archive/d9bc7cf06aef74e928f9afc3dee33b60121b9c73.zip"
sha256: "34c2d4bf7be49c2db1d2f50e3410b506aab15a06d245f8c02ea0046e9295eaa6"
mini_chromium:
url: "https://github.com/chromium/mini_chromium/archive/ccb198907cecf072d8f5b2543d4d348e834a298a.zip"
sha256: "d526f659b0d44932bb4b5ff1277d855569572eb3fcad6ec1c69a71aac6a3d6ee"
275 changes: 275 additions & 0 deletions recipes/crashpad/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
from conans import AutoToolsBuildEnvironment, ConanFile, tools
from conans.errors import ConanInvalidConfiguration
from contextlib import contextmanager
import os
import textwrap

required_conan_version = ">=1.33.0"


class CrashpadConan(ConanFile):
name = "crashpad"
description = "Crashpad is a crash-reporting system."
url = "https://github.com/conan-io/conan-center-index"
topics = ("conan", "crashpad", "crash", "error", "stacktrace", "collecting", "reporting")
license = "Apache-2.0"
homepage = "https://chromium.googlesource.com/crashpad/crashpad/+/master/README.md"
provides = "crashpad", "mini_chromium"
settings = "os", "arch", "compiler", "build_type"
madebr marked this conversation as resolved.
Show resolved Hide resolved
options = {
"fPIC": [True, False],
"http_transport": ["libcurl", "socket", None],
"with_tls": ["openssl", False],
}
default_options = {
"fPIC": True,
"http_transport": None,
"with_tls": "openssl",
}
exports_sources = "patches/*"
madebr marked this conversation as resolved.
Show resolved Hide resolved

@property
def _source_subfolder(self):
return "source_subfolder"

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
if self.settings.os in ("Linux", "FreeBSD"):
self.options.http_transport = "libcurl"
elif self.settings.os == "Android":
self.options.http_transport = "socket"

def build_requirements(self):
self.build_requires("ninja/1.10.2")
self.build_requires("gn/cci.20210429")
madebr marked this conversation as resolved.
Show resolved Hide resolved
# FIXME: needs python 2.x support on Windows (uses print without parentheses + _winreg module)

def requirements(self):
# FIXME: use mini_chromium conan package instead of embedded package
self.requires("zlib/1.2.11")
if self.settings.os in ("Linux", "FreeBSD"):
self.requires("linux-syscall-support/cci.20200813")
if self.options.http_transport != "socket":
del self.options.with_tls
if self.options.http_transport == "libcurl":
self.requires("libcurl/7.75.0")
if self.options.get_safe("with_tls") == "openssl":
self.requires("openssl/1.1.1k")

def validate(self):
if self.options.http_transport == "libcurl":
if not self.options["libcurl"].shared:
# FIXME: is this true?
self.output.warn("crashpad needs a shared libcurl library")
if self.settings.os == "Windows":
raise ConanInvalidConfiguration("Windows is not (yet) supported by this recipe because the build system requires python 2.x which is not (yet) available on CCI.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to just patch the sources? Recipe for cpython is being hard.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really still the case? depot_tools in recent versions should work fine with python 3.8, which AFAIK is the dependency that had the python issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works on Python 3.9.5 on Linux (works on my machine).
But an error is thrown when building on Windows.
Maybe it can be patched..


def source(self):
tools.get(**self.conan_data["sources"][self.version]["url"]["crashpad"], destination=self._source_subfolder, strip_root=True)
tools.get(**self.conan_data["sources"][self.version]["url"]["mini_chromium"],
destination=os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium"), strip_root=True)

@property
def _gn_os(self):
if tools.is_apple_os(self.settings.os):
if self.settings.os == "Macos":
return "mac"
else:
return "ios"
return {
"Windows": "win",
}.get(str(self.settings.os), str(self.settings.os).lower())

@property
def _gn_arch(self):
return {
"x86_64": "x64",
"armv8": "aarch64",
"x86": "x86",
}.get(str(self.settings.arch), str(self.settings.arch))

@contextmanager
def _build_context(self):
if self.settings.compiler == "Visual Studio":
with tools.vcvars(self.settings):
yield
else:
env_defaults = {}
if self.settings.compiler == "gcc":
env_defaults.update({
"CC": "gcc",
"CXX": "g++",
"LD": "g++",
})
elif self.settings.compiler in ("clang", "apple-clang"):
env_defaults.update({
"CC": "clang",
"CXX": "clang++",
"LD": "clang++",
})
env = {}
for key, value in env_defaults.items():
if not tools.get_env(key):
env[key] = value
with tools.environment_append(env):
yield

@property
def _http_transport_impl(self):
if str(self.options.http_transport) == "None":
return ""
else:
return str(self.options.http_transport)

def build(self):
# Order of ssl and crypto is wrong (first ssl, then crypto)
tools.replace_in_file(os.path.join(self._source_subfolder, "util", "BUILD.gn"), "\"crypto\"", "SSL_LABEL")
tools.replace_in_file(os.path.join(self._source_subfolder, "util", "BUILD.gn"), "\"ssl\"", "\"crypto\"")
tools.replace_in_file(os.path.join(self._source_subfolder, "util", "BUILD.gn"), "SSL_LABEL", "\"ssl\"")

tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "zlib", "BUILD.gn"), "zlib_source = \"embedded\"", "zlib_source = \"system\"")
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "common.gypi"), "-fPIC", "")
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party","mini_chromium", "mini_chromium", "build", "config", "BUILD.gn"), "-fPIC", "")

# Allow compiling crashpad with gcc (fetch compiler from environment variables)
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "config", "BUILD.gn"),
"\"clang\"", "getenv(\"CC\")")
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "config", "BUILD.gn"),
"\"clang++\"", "getenv(\"CXX\")")
toolchain_path = os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "config", "BUILD.gn")

# Use conan linux-syscall-support package
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "lss", "lss.h"),
"include \"third_party/lss/linux_syscall_support.h\"",
"include <linux_syscall_support.h>")
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "lss", "lss.h"),
"include \"third_party/lss/lss/linux_syscall_support.h\"",
"include <linux_syscall_support.h>")

tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "config", "BUILD.gn"),
"assert(false, \"Unsupported architecture\")",
"print(\"Unknown architecture -> assume conan knows how to handle it\")")

tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "win_helper.py"),
"print line", "print(line)")
tools.replace_in_file(os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build", "win_helper.py"),
"print result", "print(result)")

if self.settings.compiler == "gcc":
# Remove gcc-incompatible compiler arguments
for comp_arg in ("-Werror", "-Wheader-hygiene", "-Wnewline-eof", "-Wstring-conversion", "-Wexit-time-destructors", "-fobjc-call-cxx-cdtors", "-Wextra-semi", "-Wimplicit-fallthrough"):
tools.replace_in_file(toolchain_path,
"\"{}\"".format(comp_arg), "\"\"")

autotools = AutoToolsBuildEnvironment(self)
extra_cflags = autotools.flags + ["-D{}".format(d) for d in autotools.defines]
extra_cflags_c = []
extra_cflags_cc = autotools.cxx_flags
extra_ldflags = autotools.link_flags
if self.options.get_safe("fPIC"):
extra_cflags.append("-fPIC")
extra_cflags.extend("-I'{}'".format(inc) for inc in autotools.include_paths)
extra_ldflags.extend("-L'{}'".format(libdir) for libdir in autotools.library_paths)
if self.settings.compiler == "clang":
if self.settings.compiler.get_safe("libcxx"):
stdlib = {
"libstdc++11": "libstdc++",
}.get(str(self.settings.compiler.libcxx), str(self.settings.compiler.libcxx))
extra_cflags_cc.append("-stdlib={}".format(stdlib))
extra_ldflags.append("-stdlib={}".format(stdlib))
gn_args = [
"host_os=\\\"{}\\\"".format(self._gn_os),
"host_cpu=\\\"{}\\\"".format(self._gn_arch),
"is_debug={}".format(str(self.settings.build_type == "Debug").lower()),
"crashpad_http_transport_impl=\\\"{}\\\"".format(self._http_transport_impl),
"crashpad_use_boringssl_for_http_transport_socket={}".format(str(self.options.get_safe("with_tls", False) != False).lower()),
"extra_cflags=\\\"{}\\\"".format(" ".join(extra_cflags)),
"extra_cflags_c=\\\"{}\\\"".format(" ".join(extra_cflags_c)),
"extra_cflags_cc=\\\"{}\\\"".format(" ".join(extra_cflags_cc)),
"extra_ldflags=\\\"{}\\\"".format(" ".join(extra_ldflags)),
]
with tools.chdir(self._source_subfolder):
with self._build_context():
self.run("gn gen out/Default --args=\"{}\"".format(" ".join(gn_args)), run_environment=True)
for target in ("client", "minidump", "crashpad_handler", "snapshot"):
# FIXME: Remove verbose once everything is working hunky dory
madebr marked this conversation as resolved.
Show resolved Hide resolved
self.run("ninja -C out/Default {target} -j{parallel}".format(
target=target,
parallel=tools.cpu_count()), run_environment=True)

def package(self):
self.copy("LICENSE", src=self._source_subfolder, dst="licenses")

self.copy("*.h", src=os.path.join(self._source_subfolder, "client"), dst=os.path.join("include", "client"))
self.copy("*.h", src=os.path.join(self._source_subfolder, "util"), dst=os.path.join("include", "util"))
self.copy("*.h", src=os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "base"), dst=os.path.join("include", "base"))
self.copy("*.h", src=os.path.join(self._source_subfolder, "third_party", "mini_chromium", "mini_chromium", "build"), dst=os.path.join("include", "build"))
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("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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows there seems to be two executables provided. (missing .com)

https://chromium.googlesource.com/crashpad/crashpad/+/master/doc/overview_design.md

On Windows, this executable is built by default as a Windows GUI app, so no console will appear in normal usage. This is the version that will typically be used. A second copy is also made with a .com extension, rather than .exe. In this second copy, the PE header is modified to indicate that it’s a console app. This is useful because the .com is found in the path before the .exe, so when run normally from a shell using only the basename (without an explicit .com or .exe extension), the .com console version will be chosen, and so stdio will be hooked up as expected to the parent console so that logging output will be visible.

Copy link
Contributor Author

@madebr madebr May 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eb7a82a but untested

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it. It's called crashpad_handler_com.com.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come it's called crashpad_handler_com.com instead of just crashpad_handler.com as according to the documentation?


tools.save(os.path.join(self.package_folder, "lib", "cmake", "crashpad-cxx.cmake"),
textwrap.dedent("""\
if(TARGET crashpad::mini_chromium_base)
target_compile_features(crashpad::mini_chromium_base INTERFACE cxx_std_14)
madebr marked this conversation as resolved.
Show resolved Hide resolved
endif()
"""))

def package_info(self):
self.cpp_info.components["mini_chromium_base"].libs = ["base"]
self.cpp_info.components["mini_chromium_base"].build_modules = [os.path.join(self.package_folder, "lib", "cmake", "crashpad-cxx.cmake")]
self.cpp_info.components["mini_chromium_base"].builddirs = [os.path.join("lib", "cmake")]
if tools.is_apple_os(self.settings.os):
if self.settings.os == "Macos":
self.cpp_info.components["mini_chromium_base"].frameworks = ["ApplicationServices", "CoreFoundation", "Foundation", "IOKit", "Security"]
else: # iOS
self.cpp_info.components["mini_chromium_base"].frameworks = ["CoreFoundation", "CoreGraphics", "CoreText", "Foundation", "Security"]

self.cpp_info.components["util"].libs = ["util"]
self.cpp_info.components["util"].requires = ["mini_chromium_base", "zlib::zlib"]
if tools.is_apple_os(self.settings.os):
self.cpp_info.components["util"].libs.append("mig_output")
if self.settings.os in ("Linux", "FreeBSD"):
self.cpp_info.components["util"].libs.append("compat")
self.cpp_info.components["util"].requires.append("linux-syscall-support::linux-syscall-support")
if self.settings.os == "Windows":
self.cpp_info.components["util"].system_libs.extend(["dbghelp", "rpcrt4"])
if self.options.http_transport == "libcurl":
self.cpp_info.components["util"].requires.append("libcurl::libcurl")
elif self.options.get_safe("with_tls") == "openssl":
self.cpp_info.components["util"].requires.append("openssl::openssl")
if self.settings.os == "Macos":
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"].libs = ["client"]
self.cpp_info.components["client"].requires = ["common"]
if self.settings.os == "Windows":
self.cpp_info.components["client"].system_libs.append("rpcrt4")

self.cpp_info.components["context"].libs = ["context"]
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"]
if tools.is_apple_os(self.settings.os):
self.cpp_info.components["snapshot"].frameworks.extend(["OpenCL"])

self.cpp_info.components["format"].libs = ["format"]
self.cpp_info.components["format"].requires = ["snapshot", "mini_chromium_base", "util"]

self.cpp_info.components["minidump"].libs = ["minidump"]
self.cpp_info.components["minidump"].requires = ["snapshot", "mini_chromium_base", "util"]

self.cpp_info.components["handler"].libs = ["handler"]
self.cpp_info.components["handler"].requires = ["common", "minidump", "snapshot"]

bin_path = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bin_path))
self.env_info.PATH.append(bin_path)
9 changes: 9 additions & 0 deletions recipes/crashpad/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
21 changes: 21 additions & 0 deletions recipes/crashpad/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from conans import ConanFile, CMake, tools
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self.settings):
test_env_dir = "test_env"
tools.mkdir(test_env_dir)
bin_path = os.path.join("bin", "test_package")
handler_exe = "crashpad_handler.exe" if self.settings.os == "Windows" else "crashpad_handler"
madebr marked this conversation as resolved.
Show resolved Hide resolved
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)
48 changes: 48 additions & 0 deletions recipes/crashpad/all/test_package/test_package.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <map>
#include <string>
#include <vector>

#ifdef _WIN32
#include <cwchar>
#endif

#include "client/crashpad_client.h"
#include "client/settings.h"

bool startCrashpad(const base::FilePath &db,
const base::FilePath &handler) {
std::string url("http://localhost");
std::map<std::string, std::string> annotations;
std::vector<std::string> arguments;

crashpad::CrashpadClient client;
return client.StartHandler(
handler,
db,
db,
url,
annotations,
arguments,
true,
false
);
}

int main(int argc, char* argv[]) {
if (argc != 3) {
return 2;
}

#ifdef _WIN32
wchar_t ws[1024];
swprintf(ws, 1024, L"%hs", argv[1]);
base::FilePath db(ws);
swprintf(ws, 1024, L"%hs", argv[2]);
base::FilePath handler(ws);
#else
base::FilePath db(argv[1]);
base::FilePath handler(argv[2]);
#endif

return startCrashpad(db, handler) ? 0 : 1;
}
3 changes: 3 additions & 0 deletions recipes/crashpad/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
versions:
"cci.20210507":
folder: all