Commit ec8b64e8 authored by Marshall Greenblatt's avatar Marshall Greenblatt

Add breakpad support (issue #1131).

- General usage instructions are available at https://sites.google.com/a/chromium.org/dev/developers/testing/webkit-layout-tests/using-breakpad-with-content-shell.
- Mac: Generate "Chromium Embedded Framework.framework" using a new cef_framework target (the libcef target is now only used on Windows and Linux). Rename "Libraries/libcef.dylib" to "Chromium Embedded Framework". Distribute Release and Debug builds of the "Chromium Embedded Framework.framework" folder as part of the binary distribution.
- Mac: Fix the Xcode target compiler setting for the binary distribution so that it no longer needs to be set manually.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1524 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
parent ba361532
This diff is collapsed.
......@@ -26,6 +26,7 @@
#include "libcef/common/content_client.h"
#include "libcef/common/scheme_registration.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
......@@ -43,6 +44,14 @@
#include "ui/base/ui_base_switches.h"
#include "url/gurl.h"
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "base/debug/leak_annotations.h"
#include "base/platform_file.h"
#include "components/breakpad/app/breakpad_linux.h"
#include "components/breakpad/browser/crash_handler_host_linux.h"
#include "content/public/common/content_descriptors.h"
#endif
namespace {
// In-memory store for access tokens used by geolocation.
......@@ -278,6 +287,61 @@ void TranslatePopupFeatures(const blink::WebWindowFeatures& webKitFeatures,
}
}
#if defined(OS_POSIX) && !defined(OS_MACOSX)
breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
const std::string& process_type) {
base::FilePath dumps_path =
CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kCrashDumpsDir);
{
ANNOTATE_SCOPED_MEMORY_LEAK;
breakpad::CrashHandlerHostLinux* crash_handler =
new breakpad::CrashHandlerHostLinux(
process_type, dumps_path, false);
crash_handler->StartUploaderThread();
return crash_handler;
}
}
int GetCrashSignalFD(const CommandLine& command_line) {
if (!breakpad::IsCrashReporterEnabled())
return -1;
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
if (process_type == switches::kRendererProcess) {
static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
if (!crash_handler)
crash_handler = CreateCrashHandlerHost(process_type);
return crash_handler->GetDeathSignalSocket();
}
if (process_type == switches::kPluginProcess) {
static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
if (!crash_handler)
crash_handler = CreateCrashHandlerHost(process_type);
return crash_handler->GetDeathSignalSocket();
}
if (process_type == switches::kPpapiPluginProcess) {
static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
if (!crash_handler)
crash_handler = CreateCrashHandlerHost(process_type);
return crash_handler->GetDeathSignalSocket();
}
if (process_type == switches::kGpuProcess) {
static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
if (!crash_handler)
crash_handler = CreateCrashHandlerHost(process_type);
return crash_handler->GetDeathSignalSocket();
}
return -1;
}
#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
} // namespace
......@@ -509,6 +573,10 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
switches::kEnableReleaseDcheck,
switches::kDisablePackLoading,
switches::kResourcesDirPath,
switches::kEnableCrashReporter,
#if !defined(OS_WIN)
switches::kCrashDumpsDir,
#endif
};
command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
......@@ -763,6 +831,21 @@ std::string CefContentBrowserClient::GetDefaultDownloadName() {
return "download";
}
#if defined(OS_POSIX) && !defined(OS_MACOSX)
void CefContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
int child_process_id,
std::vector<content::FileDescriptorInfo>* mappings) {
int crash_signal_fd = GetCrashSignalFD(command_line);
if (crash_signal_fd >= 0) {
mappings->push_back(content::FileDescriptorInfo(
kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false)));
}
}
#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
#if defined(OS_WIN)
const wchar_t* CefContentBrowserClient::GetResourceDllName() {
static wchar_t file_path[MAX_PATH+1] = {0};
......
......@@ -132,6 +132,13 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
content::BrowserURLHandler* handler) OVERRIDE;
virtual std::string GetDefaultDownloadName() OVERRIDE;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
virtual void GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
int child_process_id,
std::vector<content::FileDescriptorInfo>* mappings) OVERRIDE;
#endif
#if defined(OS_WIN)
const wchar_t* GetResourceDllName() OVERRIDE;
#endif
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/common/breakpad_client.h"
#include "libcef/common/cef_switches.h"
#include "include/cef_version.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
CefBreakpadClient::CefBreakpadClient() {}
CefBreakpadClient::~CefBreakpadClient() {}
#if defined(OS_WIN)
void CefBreakpadClient::GetProductNameAndVersion(
const base::FilePath& exe_path,
base::string16* product_name,
base::string16* version,
base::string16* special_build,
base::string16* channel_name) {
*product_name = ASCIIToUTF16("cef");
*version = UTF8ToUTF16(base::StringPrintf(
"%d.%d.%d", CEF_VERSION_MAJOR, CHROME_VERSION_BUILD, CEF_REVISION));
*special_build = string16();
*channel_name = string16();
}
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
void CefBreakpadClient::GetProductNameAndVersion(std::string* product_name,
std::string* version) {
*product_name = "cef";
*version = base::StringPrintf(
"%d.%d.%d", CEF_VERSION_MAJOR, CHROME_VERSION_BUILD, CEF_REVISION);
}
base::FilePath CefBreakpadClient::GetReporterLogFilename() {
return base::FilePath(FILE_PATH_LITERAL("uploads.log"));
}
#endif
bool CefBreakpadClient::GetCrashDumpLocation(base::FilePath* crash_dir) {
#if !defined(OS_WIN)
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir))
return false;
*crash_dir = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kCrashDumpsDir);
return true;
#else
NOTREACHED();
return false;
#endif
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_BREAKPAD_CLIENT_H_
#define CEF_LIBCEF_COMMON_BREAKPAD_CLIENT_H_
#include "base/compiler_specific.h"
#include "components/breakpad/app/breakpad_client.h"
class CefBreakpadClient : public breakpad::BreakpadClient {
public:
CefBreakpadClient();
virtual ~CefBreakpadClient();
#if defined(OS_WIN)
// Returns a textual description of the product type and version to include
// in the crash report.
virtual void GetProductNameAndVersion(const base::FilePath& exe_path,
base::string16* product_name,
base::string16* version,
base::string16* special_build,
base::string16* channel_name) OVERRIDE;
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
// Returns a textual description of the product type and version to include
// in the crash report.
virtual void GetProductNameAndVersion(std::string* product_name,
std::string* version) OVERRIDE;
virtual base::FilePath GetReporterLogFilename() OVERRIDE;
#endif
// The location where minidump files should be written. Returns true if
// |crash_dir| was set.
virtual bool GetCrashDumpLocation(base::FilePath* crash_dir) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(CefBreakpadClient);
};
#endif // CEF_LIBCEF_COMMON_BREAKPAD_CLIENT_H_
......@@ -86,4 +86,7 @@ const char kEnableSpeechInput[] = "enable-speech-input";
// Enable the speech input profanity filter.
const char kEnableProfanityFilter[] = "enable-profanity-filter";
// The directory breakpad should store minidumps in.
const char kCrashDumpsDir[] = "crash-dumps-dir";
} // namespace switches
......@@ -39,6 +39,7 @@ extern const char kPersistSessionCookies[];
extern const char kEnableMediaStream[];
extern const char kEnableSpeechInput[];
extern const char kEnableProfanityFilter[];
extern const char kCrashDumpsDir[];
} // namespace switches
......
......@@ -5,13 +5,16 @@
#include "libcef/common/main_delegate.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/common/breakpad_client.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/command_line_impl.h"
#include "libcef/renderer/content_renderer_client.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
......@@ -28,16 +31,26 @@
#if defined(OS_WIN)
#include <Objbase.h> // NOLINT(build/include_order)
#include "components/breakpad/app/breakpad_win.h"
#endif
#if defined(OS_MACOSX)
#include "base/mac/os_crash_dumps.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "components/breakpad/app/breakpad_mac.h"
#include "content/public/common/content_paths.h"
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "components/breakpad/app/breakpad_linux.h"
#endif
namespace {
base::LazyInstance<CefBreakpadClient>::Leaky g_shell_breakpad_client =
LAZY_INSTANCE_INITIALIZER;
#if defined(OS_MACOSX)
base::FilePath GetFrameworksPath() {
......@@ -345,6 +358,26 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
void CefMainDelegate::PreSandboxStartup() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kEnableCrashReporter)) {
breakpad::SetBreakpadClient(g_shell_breakpad_client.Pointer());
#if defined(OS_MACOSX)
base::mac::DisableOSCrashDumps();
breakpad::InitCrashReporter();
breakpad::InitCrashProcessInfo();
#elif defined(OS_POSIX) && !defined(OS_MACOSX)
std::string process_type = command_line.GetSwitchValueASCII(
switches::kProcessType);
if (process_type != switches::kZygoteProcess)
breakpad::InitCrashReporter();
#elif defined(OS_WIN)
UINT new_flags =
SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
UINT existing_flags = SetErrorMode(new_flags);
SetErrorMode(existing_flags | new_flags);
breakpad::InitCrashReporter();
#endif
}
#if defined(OS_MACOSX)
if (!command_line.HasSwitch(switches::kProcessType)) {
// Only override the child process path when executing the main process.
......@@ -396,6 +429,14 @@ void CefMainDelegate::ProcessExiting(const std::string& process_type) {
ResourceBundle::CleanupSharedInstance();
}
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
void CefMainDelegate::ZygoteForked() {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableCrashReporter)) {
breakpad::InitCrashReporter();
}
}
#endif
content::ContentBrowserClient* CefMainDelegate::CreateContentBrowserClient() {
browser_client_.reset(new CefContentBrowserClient);
......
......@@ -39,6 +39,9 @@ class CefMainDelegate : public content::ContentMainDelegate {
const std::string& process_type,
const content::MainFunctionParams& main_function_params) OVERRIDE;
virtual void ProcessExiting(const std::string& process_type) OVERRIDE;
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
virtual void ZygoteForked() OVERRIDE;
#endif
virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
virtual content::ContentRendererClient*
CreateContentRendererClient() OVERRIDE;
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.chromium.ContentShell.framework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSignature</key>
<string>????</string>
</dict>
</plist>
......@@ -475,7 +475,7 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
std::transform(url.begin(), url.end(), url.begin(), tolower);
std::string startupURL = GetStartupURL();
if (url.find(startupURL) != 0)
if (startupURL != "chrome://crash" && url.find(startupURL) != 0)
frame->LoadURL(startupURL);
}
......
......@@ -5,6 +5,7 @@
{
'variables': {
'chromium_code': 1,
'framework_name': 'Chromium Embedded Framework',
'linux_use_gold_binary': 0,
'linux_use_gold_flags': 0,
'conditions': [
......@@ -147,26 +148,12 @@
],
'copies': [
{
# Add library dependencies to the bundle.
'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/',
'files': [
'$(CONFIGURATION)/libcef.dylib',
'$(CONFIGURATION)/ffmpegsumo.so',
],
},
{
# Add other resources to the bundle.
'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/Frameworks/Chromium Embedded Framework.framework/',
'files': [
'Resources/',
],
},
{
# Add the helper app.
# Add the framework and helper app.
'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/Frameworks',
'files': [
'<(PRODUCT_DIR)/cefclient Helper.app',
'$(CONFIGURATION)/<(framework_name).framework/',
'$(CONFIGURATION)/libplugin_carbon_interpose.dylib',
'<(PRODUCT_DIR)/cefclient Helper.app',
],
},
],
......@@ -176,8 +163,8 @@
'action': [
'install_name_tool',
'-change',
'@executable_path/libcef.dylib',
'@executable_path/../Frameworks/Chromium Embedded Framework.framework/Libraries/libcef.dylib',
'@executable_path/<(framework_name)',
'@executable_path/../Frameworks/<(framework_name).framework/<(framework_name)',
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}'
],
},
......@@ -202,7 +189,7 @@
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
'$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
'$(CONFIGURATION)/libcef.dylib',
'$(CONFIGURATION)/<(framework_name).framework/<(framework_name)',
],
},
'sources': [
......@@ -320,7 +307,7 @@
'link_settings': {
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
'$(CONFIGURATION)/libcef.dylib',
'$(CONFIGURATION)/<(framework_name).framework/<(framework_name)',
],
},
'sources': [
......@@ -351,8 +338,8 @@
'action': [
'install_name_tool',
'-change',
'@executable_path/libcef.dylib',
'@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Libraries/libcef.dylib',
'@executable_path/<(framework_name)',
'@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)',
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}'
],
},
......
CONTENTS
--------
Release Contains libcef.dylib and other components required to run the
release version of CEF-based applications.
Resources Contains images and resources required by applications using CEF.
The contents of this folder should be transferred to the
Contents/Resources folder in the app bundle.
Release Contains the "Chromium Embedded Framework.framework" and other
components required to run the release version of CEF-based
applications.
USAGE
......
......@@ -6,10 +6,67 @@ the "required" section must be redistributed with all applications using CEF.
Components listed under the "optional" section may be excluded if the related
features will not be used.
Applications using CEF on OS X must follow a specific app bundle structure.
Replace "cefclient" in the below example with your application name.
cefclient.app/
Contents/
Frameworks/
Chromium Embedded Framework.framework/
Chromium Embedded Framework <= main application library
Libraries/
ffmpegsumo.so <= HTML5 audio/video support library
Resources/
cef.pak, devtools_resources.pak <= non-localized resources and strings
crash_inspector, crash_report_sender <= breakpad support
en.lproj/, ... <= locale-specific resources and strings
Info.plist
libplugin_carbon_interpose.dylib <= plugin support library
cefclient Helper.app/
Contents/
Info.plist
MacOS/
cefclient Helper <= helper executable
Pkginfo
cefclient Helper EH.app/
Contents/
Info.plist
MacOS/
cefclient Helper EH <= helper executable
Pkginfo
cefclient Helper NP.app/
Contents/
Info.plist
MacOS/
cefclient Helper NP <= helper executable
Pkginfo
Info.plist
MacOS/
cefclient <= cefclient application executable
Pkginfo
Resources/
binding.html, ... <= cefclient application resources
The "Chromium Embedded Framework.framework" is an unversioned framework that
contains CEF binaries and resources. Executables (cefclient, cefclient Helper,
etc) are linked to the "Chromium Embedded Framework" library using
install_name_tool and a path relative to @executable_path.
The "cefclient Helper" apps are used for executing separate processes
(renderer, plugin, etc) with different characteristics. They need to have
separate app bundles and Info.plist files so that, among other things, they
don't show dock icons. The "EH" helper, which is used when launching plugin
processes, has the MH_NO_HEAP_EXECUTION bit cleared to allow an executable
heap. The "NP" helper, which is used when launching NaCl plugin processes
only, has the MH_PIE bit cleared to disable ASLR. This is set up as part of
the build process using scripts from the tools/ directory. Examine the Xcode
project included with the binary distribution or the originating cefclient.gyp
file for a better idea of the script dependencies.
Required components:
* CEF core library
libcef.dylib
* CEF framework library
Chromium Embedded Framework.framework/Chromium Embedded Framework
* Plugin support library
libplugin_carbon_interpose.dylib
......@@ -17,7 +74,7 @@ Required components:
Optional components:
* Localized resources
Resources/*.lproj/
Chromium Embedded Framework.framework/Resources/*.lproj/
Note: Contains localized strings for WebKit UI controls. A .pak file is loaded
from this folder based on the CefSettings.locale value. Only configured
locales need to be distributed. If no locale is configured the default locale
......@@ -25,12 +82,18 @@ Optional components:
CefSettings.pack_loading_disabled.
* Other resources
Resources/cef.pak
Resources/devtools_resources.pak
Chromium Embedded Framework.framework/Resources/cef.pak
Chromium Embedded Framework.framework/Resources/devtools_resources.pak
Note: Contains WebKit image and inspector resources. Pack file loading can be
disabled completely using CefSettings.pack_loading_disabled. The resources
directory path can be customized using CefSettings.resources_dir_path.
* FFmpeg audio and video support
ffmpegsumo.so
Chromium Embedded Framework.framework/Libraries/ffmpegsumo.so
Note: Without this component HTML5 audio and video will not function.
* Breakpad support
Chromium Embedded Framework.framework/Resources/crash_inspector
Chromium Embedded Framework.framework/Resources/crash_report_sender
Chromium Embedded Framework.framework/Resources/Info.plist
Note: Without these components breakpad support will not function.
......@@ -4,20 +4,18 @@ CONTENTS
cefclient Contains the cefclient sample application configured to build
using the files in this distribution.
Debug Contains libcef.dylib and other components required to run the debug
version of CEF-based applications.
Debug Contains the "Chromium Embedded Framework.framework" and other
components required to run the debug version of CEF-based
applications.
include Contains all required CEF header files.
libcef_dll Contains the source code for the libcef_dll_wrapper static library
that all applications using the CEF C++ API must link against.
Release Contains libcef.dylib and other components required to run the
release version of CEF-based applications.
Resources Contains images and resources required by applications using CEF.
The contents of this folder should be transferred to the
Contents/Resources folder in the app bundle.
Release Contains the "Chromium Embedded Framework.framework" and other
components required to run the release version of CEF-based
applications.
tools Scripts that perform post-processing on Mac release targets.
......@@ -27,10 +25,6 @@ USAGE
Xcode 3 and 4: Open the cefclient.xcodeproj project and build.
When using Xcode 4.2 or newer you will need to change the "Compiler for
C/C++/Objective-C" setting to "LLVM GCC 4.2" under "Build Settings" for
each target.
Please visit the CEF Website for additional usage information.
http://code.google.com/p/chromiumembedded
......@@ -221,12 +221,22 @@ def create_xcode_projects():
gyper = [ 'python', 'tools/gyp_cef', os.path.relpath(os.path.join(output_dir, 'cefclient.gyp'), cef_dir) ]
RunAction(cef_dir, gyper);
# Post-process the Xcode project to fix file paths
# Post-process the Xcode project file.
src_file = os.path.join(output_dir, 'cefclient.xcodeproj/project.pbxproj')
data = read_file(src_file)
# Fix file paths.
data = data.replace('../../../build/mac/', 'tools/')
data = data.replace('../../../build', 'build')
data = data.replace('../../../xcodebuild', 'xcodebuild')
# Fix framework type.
data = data.replace('lastKnownFileType = text; name = "Chromium Embedded Framework";', \
'explicitFileType = "compiled.mach-o.dylib"; name = "Chromium Embedded Framework";')
# Fix target compiler.
data = data.replace('GCC_VERSION = 4.2;', 'GCC_VERSION = com.apple.compilers.llvm.clang.1_0;')
write_file(src_file, data)
def create_make_projects():
......@@ -588,6 +598,7 @@ elif platform == 'macosx':
out_dir = os.path.join(src_dir, 'xcodebuild')
valid_build_dir = None
framework_name = 'Chromium Embedded Framework'
if mode == 'standard':
# transfer Debug files
......@@ -596,8 +607,8 @@ elif platform == 'macosx':
valid_build_dir = build_dir
dst_dir = os.path.join(output_dir, 'Debug')
make_dir(dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'ffmpegsumo.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'libcef.dylib'), dst_dir, options.quiet)
copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \
os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet)
copy_file(os.path.join(build_dir, 'libplugin_carbon_interpose.dylib'), dst_dir, options.quiet)
# transfer Release files
......@@ -607,8 +618,8 @@ elif platform == 'macosx':
dst_dir = os.path.join(output_dir, 'Release')
make_dir(dst_dir, options.quiet)
if mode != 'client':
copy_file(os.path.join(build_dir, 'ffmpegsumo.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'libcef.dylib'), dst_dir, options.quiet)