Skip to content

Commit da6bbed

Browse files
committed
Fix Mac error: icudtl.dat not found in bundle (cztomczak#304)...
hello_world.py example runs fine on Mac! Add "Location of CEF framework in Mac apps" to Knowledge Base. Set ApplicationSettings.framework_dir_path when not set during a call to cef.Initialize(). Also set resources_dir_path. Fix rpath to "@loader_path/" so that libraries load correctly. Other fixes in build tools and in docs.
1 parent b2861c0 commit da6bbed

File tree

7 files changed

+120
-54
lines changed

7 files changed

+120
-54
lines changed

api/API-index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* [context_menu](ApplicationSettings.md#context_menu)
1313
* [downloads_enabled](ApplicationSettings.md#downloads_enabled)
1414
* [external_message_pump](ApplicationSettings.md#external_message_pump)
15+
* [framework_dir_path](ApplicationSettings.md#framework_dir_path)
1516
* [ignore_certificate_errors](ApplicationSettings.md#ignore_certificate_errors)
1617
* [javascript_flags](ApplicationSettings.md#javascript_flags)
1718
* [locale](ApplicationSettings.md#locale)
@@ -113,7 +114,6 @@
113114
* [accept_language_list](BrowserSettings.md#accept_language_list)
114115
* [application_cache_disabled](BrowserSettings.md#application_cache_disabled)
115116
* [background_color](BrowserSettings.md#background_color)
116-
* [caret_browsing_enabled](BrowserSettings.md#caret_browsing_enabled)
117117
* [databases_disabled](BrowserSettings.md#databases_disabled)
118118
* [default_encoding](BrowserSettings.md#default_encoding)
119119
* [dom_paste_disabled](BrowserSettings.md#dom_paste_disabled)

api/ApplicationSettings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ then the framework must exist at "Contents/Frameworks/Chromium Embedded
189189
Framework.framework" in the top-level app bundle. Also configurable using
190190
the "framework-dir-path" command-line switch.
191191

192-
See also Issue #304.
192+
See also [Issue #304](../../../issues/304).
193193

194194

195195
### ignore_certificate_errors

docs/Knowledge-Base.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,48 @@ they are all unicode strings. Be aware of this when porting cefpython
5050
based apps to Python 3, as it may cause issues.
5151

5252

53+
## Location of CEF framework in Mac apps
54+
55+
This information here is for when creating apps for distribution
56+
on Mac.
57+
58+
By default CEF expects that CEF framework is located at
59+
`Contents/Frameworks/Chromium Embedded Framework.framework`
60+
in the top-level app bundle. If that is not the case then you have
61+
to set ApplicationSettings.[framework_dir_path]
62+
(../api/ApplicationSettings.md#framework_dir_path) before calling
63+
cef.Initialize().
64+
65+
You may also need to change the structure and embedded paths in
66+
CEF framework and in the cefpython module. Here are the default
67+
settings:
68+
```
69+
cefpython_package/
70+
cefpython_py27.so
71+
rpath=@loader_path
72+
load:@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework
73+
Chromium Embedded Framework.framework/
74+
Chromium Embedded Framework
75+
id:@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework
76+
```
77+
78+
When creating Mac app for distribution you may want to change
79+
directory structure, so you might have to change these settings
80+
embedded in these libraries. You can do so with these commands:
81+
82+
```
83+
install_name_tool -rpath old new
84+
install_name_tool -change old new
85+
install_name_tool -id name
86+
```
87+
88+
To check whether it succeeded run these commands:
89+
```
90+
otool -l file
91+
otool -L file
92+
```
93+
94+
5395
## Flash support
5496

5597
See [Issue #235](../../../issues/235) ("Flash support in CEF 51+").

src/cefpython.pyx

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -577,12 +577,18 @@ cdef public int CommandLineSwitches_GetInt(const char* key) except * with gil:
577577
# is called. See Issue #73 in the CEF Python Issue Tracker.
578578

579579
def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
580+
# applicationSettings and commandLineSwitches argument
581+
# names are kept for backward compatibility.
582+
application_settings = applicationSettings
583+
command_line_switches = commandLineSwitches
580584

581585
# Alternative names for existing parameters
582586
if "settings" in kwargs:
583-
applicationSettings = kwargs["settings"]
587+
assert not applicationSettings, "Bad arguments"
588+
application_settings = kwargs["settings"]
584589
if "switches" in kwargs:
585-
commandLineSwitches = kwargs["switches"]
590+
assert not command_line_switches, "Bad arguments"
591+
command_line_switches = kwargs["switches"]
586592

587593
IF UNAME_SYSNAME == "Linux":
588594
# Fix Issue #231 - Discovery of the "icudtl.dat" file fails on Linux.
@@ -595,16 +601,17 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
595601
or Debug("ERROR: CefOverridePath failed")
596602
# END IF UNAME_SYSNAME == "Linux":
597603

598-
if not applicationSettings:
599-
applicationSettings = {}
604+
if not application_settings:
605+
application_settings = {}
606+
600607
# Debug settings need to be set before Debug() is called
601608
# and before the CefPythonApp class is instantiated.
602609
global g_debug
603610
global g_debugFile
604-
if "debug" in applicationSettings:
605-
g_debug = bool(applicationSettings["debug"])
606-
if "log_file" in applicationSettings:
607-
g_debugFile = applicationSettings["log_file"]
611+
if "debug" in application_settings:
612+
g_debug = bool(application_settings["debug"])
613+
if "log_file" in application_settings:
614+
g_debugFile = application_settings["log_file"]
608615

609616
Debug("Initialize() called")
610617

@@ -617,65 +624,79 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
617624
# -------------------------------------------------------------------------
618625
# CEF Python only options - default values
619626

620-
if "debug" not in applicationSettings:
621-
applicationSettings["debug"] = False
622-
if "log_severity" not in applicationSettings:
627+
if "debug" not in application_settings:
628+
application_settings["debug"] = False
629+
if "log_severity" not in application_settings:
623630
# By default show only errors. Don't show on Linux X server non-fatal
624631
# errors like "WARNING:x11_util.cc(1409)] X error received".
625-
applicationSettings["log_severity"] = LOGSEVERITY_ERROR
626-
if "string_encoding" not in applicationSettings:
627-
applicationSettings["string_encoding"] = "utf-8"
628-
if "unique_request_context_per_browser" not in applicationSettings:
629-
applicationSettings["unique_request_context_per_browser"] = False
630-
if "downloads_enabled" not in applicationSettings:
631-
applicationSettings["downloads_enabled"] = True
632-
if "remote_debugging_port" not in applicationSettings:
633-
applicationSettings["remote_debugging_port"] = 0
634-
if "auto_zooming" not in applicationSettings:
632+
application_settings["log_severity"] = LOGSEVERITY_ERROR
633+
if "string_encoding" not in application_settings:
634+
application_settings["string_encoding"] = "utf-8"
635+
if "unique_request_context_per_browser" not in application_settings:
636+
application_settings["unique_request_context_per_browser"] = False
637+
if "downloads_enabled" not in application_settings:
638+
application_settings["downloads_enabled"] = True
639+
if "remote_debugging_port" not in application_settings:
640+
application_settings["remote_debugging_port"] = 0
641+
if "auto_zooming" not in application_settings:
635642
IF UNAME_SYSNAME == "Windows":
636643
if DpiAware.IsProcessDpiAware():
637-
applicationSettings["auto_zooming"] = "system_dpi"
644+
application_settings["auto_zooming"] = "system_dpi"
638645

639646
# Paths
640647
cdef str module_dir = GetModuleDirectory()
641-
if "locales_dir_path" not in applicationSettings:
648+
if platform.system() == "Darwin":
649+
if "framework_dir_path" not in application_settings:
650+
application_settings["framework_dir_path"] = os.path.join(
651+
module_dir, "Chromium Embedded Framework.framework")
652+
# Bug in CEF: CefSettings.framework_dir_path doesn't work.
653+
# Can be worked around by setting command line switch.
654+
if not command_line_switches:
655+
command_line_switches = {}
656+
if "framework-dir-path" not in command_line_switches:
657+
command_line_switches["framework-dir-path"] = \
658+
application_settings["framework_dir_path"]
659+
if "locales_dir_path" not in application_settings:
642660
if platform.system() != "Darwin":
643-
applicationSettings["locales_dir_path"] = os.path.join(
661+
application_settings["locales_dir_path"] = os.path.join(
644662
module_dir, "locales")
645-
if "resources_dir_path" not in applicationSettings:
646-
applicationSettings["resources_dir_path"] = module_dir
663+
if "resources_dir_path" not in application_settings:
664+
application_settings["resources_dir_path"] = module_dir
647665
if platform.system() == "Darwin":
648-
pass # TODO: Check if this needs to be set in v56+
649-
if "browser_subprocess_path" not in applicationSettings:
650-
applicationSettings["browser_subprocess_path"] = os.path.join(
666+
# "framework_dir_path" will always be set, see code above.
667+
application_settings["resources_dir_path"] = os.path.join(
668+
application_settings["framework_dir_path"],
669+
"Resources")
670+
if "browser_subprocess_path" not in application_settings:
671+
application_settings["browser_subprocess_path"] = os.path.join(
651672
module_dir, "subprocess")
652673

653674
# Mouse context menu
654-
if "context_menu" not in applicationSettings:
655-
applicationSettings["context_menu"] = {}
675+
if "context_menu" not in application_settings:
676+
application_settings["context_menu"] = {}
656677
menuItems = ["enabled", "navigation", "print", "view_source",
657678
"external_browser", "devtools"]
658679
for item in menuItems:
659-
if item not in applicationSettings["context_menu"]:
660-
applicationSettings["context_menu"][item] = True
680+
if item not in application_settings["context_menu"]:
681+
application_settings["context_menu"][item] = True
661682

662683
# Remote debugging port. If value is 0 we will generate a random
663684
# port. To disable remote debugging set value to -1.
664-
if applicationSettings["remote_debugging_port"] == 0:
685+
if application_settings["remote_debugging_port"] == 0:
665686
# Generate a random port.
666-
applicationSettings["remote_debugging_port"] =\
687+
application_settings["remote_debugging_port"] =\
667688
random.randint(49152, 65535)
668-
elif applicationSettings["remote_debugging_port"] == -1:
689+
elif application_settings["remote_debugging_port"] == -1:
669690
# Disable remote debugging
670-
applicationSettings["remote_debugging_port"] = 0
691+
application_settings["remote_debugging_port"] = 0
671692

672693
# -------------------------------------------------------------------------
673694

674695
# CEF options - default values.
675-
if not "multi_threaded_message_loop" in applicationSettings:
676-
applicationSettings["multi_threaded_message_loop"] = False
677-
if not "single_process" in applicationSettings:
678-
applicationSettings["single_process"] = False
696+
if not "multi_threaded_message_loop" in application_settings:
697+
application_settings["multi_threaded_message_loop"] = False
698+
if not "single_process" in application_settings:
699+
application_settings["single_process"] = False
679700

680701
cdef CefRefPtr[CefApp] cefApp = <CefRefPtr[CefApp]?>new CefPythonApp()
681702

@@ -698,21 +719,21 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
698719
# Make a copy as applicationSettings is a reference only
699720
# that might get destroyed later.
700721
global g_applicationSettings
701-
for key in applicationSettings:
702-
g_applicationSettings[key] = copy.deepcopy(applicationSettings[key])
722+
for key in application_settings:
723+
g_applicationSettings[key] = copy.deepcopy(application_settings[key])
703724

704725
cdef CefSettings cefApplicationSettings
705726
# No sandboxing for the subprocesses
706727
cefApplicationSettings.no_sandbox = 1
707-
SetApplicationSettings(applicationSettings, &cefApplicationSettings)
728+
SetApplicationSettings(application_settings, &cefApplicationSettings)
708729

709-
if commandLineSwitches:
730+
if command_line_switches:
710731
# Make a copy as commandLineSwitches is a reference only
711732
# that might get destroyed later.
712733
global g_commandLineSwitches
713-
for key in commandLineSwitches:
734+
for key in command_line_switches:
714735
g_commandLineSwitches[key] = copy.deepcopy(
715-
commandLineSwitches[key])
736+
command_line_switches[key])
716737

717738
# External message pump
718739
if GetAppSetting("external_message_pump")\

src/subprocess/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ subprocess:
5555
$(CPP_FILES) \
5656
$(CEF_LINK_FLAGS) \
5757
$(LIBS) -lcef_dll_wrapper \
58-
-o subprocess -Wl,-rpath,.
58+
-o subprocess -Wl,-rpath,@loader_path/

tools/build.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
from sources or use ready binaries from Spotify Automated Builds.
1818
1919
Usage:
20-
build.py VERSION [--rebuild-cpp] [--fast] [--kivy]
20+
build.py VERSION [--rebuild-cpp] [--fast] [--clean] [--kivy]
2121
2222
Options:
2323
VERSION Version in format xx.xx
2424
--rebuild-cpp Force rebuild of C++ projects
2525
--fast Fast mode
26+
--clean Clean C++ projects build files (.o .a etc)
2627
--kivy Run only Kivy example
2728
"""
2829

@@ -221,7 +222,8 @@ def check_cython_version():
221222

222223

223224
def command_line_args():
224-
global DEBUG_FLAG, FAST_FLAG, KIVY_FLAG, REBUILD_CPP, VERSION
225+
global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\
226+
REBUILD_CPP, VERSION
225227

226228
print("[build.py] Parse command line arguments")
227229

@@ -393,7 +395,7 @@ def compile_cpp_projects_unix():
393395
print("[build.py] Compile C++ projects")
394396
if CLEAN_FLAG:
395397
print("[build.py] Clean C++ projects (--clean flag passed)")
396-
clean_cpp_projects_unix()
398+
clean_cpp_projects_unix()
397399

398400
# Need to allow continuing even when make fails, as it may
399401
# fail because the "public" function declaration is not yet
@@ -686,6 +688,7 @@ def delete_files_by_pattern(pattern):
686688
files = glob.glob(pattern)
687689
for f in files:
688690
os.remove(f)
691+
print("[build.py] Removed {0} files".format(len(files)))
689692

690693

691694
def delete_directories_by_pattern(pattern):

tools/build_module.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def set_compiler_options(options):
229229
"-Wl,-search_paths_first",
230230
"-F"+os.path.join(CEF_BINARIES_LIBRARIES, "bin"),
231231
"-framework", "Chromium Embedded Framework",
232-
"-Wl,-rpath,@loader_path",
232+
"-Wl,-rpath,@loader_path/", # ending slash is crucial!
233233
])
234234
if not FAST_FLAG:
235235
extra_link_args.extend([

0 commit comments

Comments
 (0)