Commit e430e495 authored by mark@chromium.org's avatar mark@chromium.org

Allow use of ^blocks, even with the 10.5 SDK, and even with a 10.5 runtime.

BUG=91978
TEST=none
Review URL: http://codereview.chromium.org/7582032

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95892 0039d316-1c4b-4281-b951-d872f2087c98
parent d2a6c0e3
# Copyright (c) 2011 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.
# Definitions of symbols that may be needed at runtime but aren't necessarily
# present in the SDK chosen for compilation.
#
# This file provides a symbols for _NSConcreteGlobalBlock and
# _NSConcreteStackBlock, normally present in libSystem.dylib and provided by
# by libclosure-38/data.c in Mac OS X 10.6 and later. When using the 10.5 SDK,
# the symbol is not present. This file's definition can be used with extreme
# care in an application that needs to use the 10.5 SDK in conjunction with
# blocks.
#
# This file cooperates with the build system (closure_leopard_compat.gyp) to
# produce a dynamic library that, when linked against, causes dependents to
# look in libSystem for the symbols provided here. It also cooperates with a
# header (block.h) that causes dependents to treat the symbols provided here
# as weak imports, critical for the resultant output to be loadable on 10.5.
# To simplify things, this file assumes it's being built with the 10.5 SDK,
# a deployment target of 10.5, and is producing 32-bit x86 code. Other
# combinations are possible, but not interesting for the time being. See
# <sys/cdefs.h> for interesting ways that names might be mangled in other
# configurations.
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED != MAC_OS_X_VERSION_10_5 || \
MAC_OS_X_VERSION_MAX_ALLOWED != MAC_OS_X_VERSION_10_5 || \
!defined(__i386__)
#error This file only supports 32-bit x86 code with both SDK and DT set to 10.5
#endif
#define DEFINE_GLOBAL_SYMBOL(name) \
.globl name ## ;\
name ## :
.section __DATA,__data
DEFINE_GLOBAL_SYMBOL(__NSConcreteGlobalBlock)
DEFINE_GLOBAL_SYMBOL(__NSConcreteStackBlock)
# When this file is in use, the linker is expected to link things against both
# this file and the real copy of libSystem present in the SDK. When doing so,
# the linker is smart enough to produce only one LC_LOAD_DYLIB load command.
# However, it's not smart enough to notice that while this file's dylib only
# provides weak-imported symbols, the real libSystem's dylib does not.
# Consequently, it may produce an LC_LOAD_WEAK_DYLIB load command for
# libSystem instead of an ordinary LC_LOAD_DYLIB command. LC_LOAD_WEAK_DYLIB
# declares that any symbol offered by the library, and in fact the entire
# library, is permitted to be missing at runtime. This is entirely
# inappropriate for libSystem. To counteract this problem, this file also
# defines some other symbols that libSystem provides. Dependents of this
# library are not expected to treat these other symbols as weak imports. In
# order for any dependent that links against this library to load it with an
# LC_LOAD_DYLIB command instead of an LC_LOAD_WEAK_DYLIB command, this library
# must satisfy at least one unresolved non-weak-import symbol required by the
# dependent.
.text
# |exit| is a good one: because it's referenced by crt1.o, ordinary executables
# are guaranteed to need this symbol. Unfortunately, there's no such symbol in
# dylib1.o that libSystem is expected to provide, so a few other common libc
# symbols are thrown into the mix.
DEFINE_GLOBAL_SYMBOL(_exit)
# Include |close| because well-written programs that use the standard library
# are likely to refer to it. Include |open| for good measure because it goes
# pretty well with this. Include the stdio abstractions for these functions
# as well.
DEFINE_GLOBAL_SYMBOL(_close$UNIX2003)
DEFINE_GLOBAL_SYMBOL(_open$UNIX2003)
DEFINE_GLOBAL_SYMBOL(_fclose)
DEFINE_GLOBAL_SYMBOL(_fopen)
DEFINE_GLOBAL_SYMBOL(_fdopen)
DEFINE_GLOBAL_SYMBOL(_freopen$UNIX2003)
# Commonly-used allocation functions.
DEFINE_GLOBAL_SYMBOL(_malloc)
DEFINE_GLOBAL_SYMBOL(_calloc)
DEFINE_GLOBAL_SYMBOL(_realloc)
DEFINE_GLOBAL_SYMBOL(_reallocf)
DEFINE_GLOBAL_SYMBOL(_valloc)
DEFINE_GLOBAL_SYMBOL(_free)
# Include |printf|, |fprintf|, |sprintf|, |snprintf|, and |puts|, because
# small test programs are likely to refer to one of these. puts is rarely
# invoked directly, but the compiler may optimize simple printf calls into
# puts calls.
DEFINE_GLOBAL_SYMBOL(_printf)
DEFINE_GLOBAL_SYMBOL(_fprintf)
DEFINE_GLOBAL_SYMBOL(_sprintf)
DEFINE_GLOBAL_SYMBOL(_snprintf)
DEFINE_GLOBAL_SYMBOL(_puts)
# Some <string.h> functions that are commonly used.
DEFINE_GLOBAL_SYMBOL(_memcmp)
DEFINE_GLOBAL_SYMBOL(_memcpy)
DEFINE_GLOBAL_SYMBOL(_memmove)
DEFINE_GLOBAL_SYMBOL(_memset)
DEFINE_GLOBAL_SYMBOL(_strcasecmp)
DEFINE_GLOBAL_SYMBOL(_strcat)
DEFINE_GLOBAL_SYMBOL(_strchr)
DEFINE_GLOBAL_SYMBOL(_strcmp)
DEFINE_GLOBAL_SYMBOL(_strcpy)
DEFINE_GLOBAL_SYMBOL(_strdup)
DEFINE_GLOBAL_SYMBOL(_strlcat)
DEFINE_GLOBAL_SYMBOL(_strlcpy)
DEFINE_GLOBAL_SYMBOL(_strlen)
DEFINE_GLOBAL_SYMBOL(_strncasecmp)
DEFINE_GLOBAL_SYMBOL(_strncat)
DEFINE_GLOBAL_SYMBOL(_strncmp)
DEFINE_GLOBAL_SYMBOL(_strncpy)
DEFINE_GLOBAL_SYMBOL(_strnstr)
DEFINE_GLOBAL_SYMBOL(_strstr)
# Some data-section symbols that might be referenced.
.section __DATA,__data
DEFINE_GLOBAL_SYMBOL(___stdinp)
DEFINE_GLOBAL_SYMBOL(___stdoutp)
DEFINE_GLOBAL_SYMBOL(___stderrp)
#undef DEFINE_GLOBAL_SYMBOL
// Copyright (c) 2011 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 CHROME_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
#define CHROME_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
#pragma once
// libclosure (blocks) compatibilty for Mac OS X 10.5 (Leopard)
//
// Background material:
// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks
// http://opensource.apple.com/source/libclosure/libclosure-38/
//
// Leopard doesn't support blocks. Chrome supports Leopard. Chrome needs to use
// blocks.
//
// In any file where you use blocks (any time you type ^{...}), you must
// #include this file to ensure that the runtime symbols referenced by code
// emitted by the compiler are marked for weak-import. This means that if
// these symbols are not present at runtime, the program will still load, but
// their values will be NULL.
//
// In any target (in the GYP sense) where you use blocks, you must also depend
// on the closure_blocks_leopard_compat target to ensure that these symbols
// will be available at link time, even when the 10.5 SDK is in use. This
// This allows the continued use of the 10.5 SDK, which does not contain these
// symbols.
//
// This does not relieve you of the responsibility to not use blocks on
// Leopard. Because runtime support for Blocks still isn't present on that
// operating system, the weak-imported symbols will have value 0 and attempts
// to do anything meaningful with them will fail or crash. You must take care
// not to enter any codepath that uses blocks on Leopard. The base::mac::IsOS*
// family may be helpful.
//
// Although this scheme allows the use of the 10.5 SDK and 10.5 runtime in an
// application that uses blocks, it is still necessary to use a compiler that
// supports blocks. GCC 4.2 as shipped with Xcode 3.2 for Mac OS X 10.6
// qualifies, as do sufficiently recent versions of clang. GCC 4.2 as shipped
// with Xcode 3.1 for Mac OS X 10.5 does not qualify.
// _NSConcreteGlobalBlock and _NSConcreteStackBlock are a private
// implementation details of libclosure defined in
// libclosure/libclosure-38/Block_private.h, but they're exposed from
// libSystem as public symbols, and the block-enabled compiler will emit code
// that references these symbols. Because the symbols aren't present in 10.5's
// libSystem, they must be declared as weak imports in any file that uses
// blocks. Any block-using file must #include this header to guarantee that
// the symbols will show up in linked output as weak imports when compiling
// for a 10.5 deployment target. Because the symbols are always present in
// 10.6 and higher, they do not need to be a weak imports when the deployment
// target is at least 10.6.
//
// Both GCC and clang emit references to these symbols, providing implicit
// declarations as needed, but respecting any user declaration when present.
// See gcc-5666.3/gcc/c-parser.c build_block_struct_initlist,
// gcc-5666.3/gcc/cp/parser.c build_block_struct_initlist, and
// clang-2.9/lib/CodeGen/CodeGenModule.cpp
// CodeGenModule::getNSConcreteGlobalBlock() and
// CodeGenModule::getNSConcreteStackBlock().
#include <AvailabilityMacros.h>
extern "C" {
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 // DT <= 10.5
#define MAYBE_WEAK_IMPORT __attribute__((weak_import))
#else // DT > 10.5
#define MAYBE_WEAK_IMPORT
#endif // DT <= 10.5
MAYBE_WEAK_IMPORT extern void* _NSConcreteGlobalBlock[32];
MAYBE_WEAK_IMPORT extern void* _NSConcreteStackBlock[32];
#undef MAYBE_WEAK_IMPORT
} // extern "C"
#endif // CHROME_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
#include "base/mac/mac_util.h"
#include "chrome/browser/mac/closure_blocks_leopard_compat.h"
namespace {
// It should be possible to declare a block on OSes as early as Leopard
// (10.5). This should be buildable with the 10.5 SDK and a 10.5 deployment
// target, and runnable on 10.5. However, the block itself is not expected to
// be runnable on 10.5. This test verfies that blocks are buildable on 10.5
// and runnable on Snow Leopard (10.6) and later.
TEST(ClosureBlocksLeopardCompatTest, Basic) {
bool ran = false;
void (^test_block)(bool*) = ^(bool* ran_pointer) { *ran_pointer = true; };
ASSERT_FALSE(ran);
if (base::mac::IsOSSnowLeopardOrLater()) {
test_block(&ran);
ASSERT_TRUE(ran);
}
}
} // namespace
...@@ -4904,4 +4904,55 @@ ...@@ -4904,4 +4904,55 @@
'hard_dependency': 1, 'hard_dependency': 1,
}, },
], ],
'conditions': [
['OS=="mac"', {
'targets': [
{
'target_name': 'closure_blocks_leopard_compat',
'conditions': [
['mac_sdk == "10.5"', {
'type': 'shared_library',
'product_name': 'closure_blocks_leopard_compat_stub',
'sources': [
'browser/mac/closure_blocks_leopard_compat.S',
],
'xcode_settings': {
# These values are taken from libSystem.dylib in the 10.5 SDK.
# Setting LD_DYLIB_INSTALL_NAME causes anything linked against
# this stub library to look for the symbols it provides in the
# real libSystem at runtime. The real library's compatibility
# version is used, and the value of the current version from
# the SDK is used to make it appear as though anything linked
# against this stub was linked against the real thing.
'LD_DYLIB_INSTALL_NAME': '/usr/lib/libSystem.B.dylib',
'DYLIB_COMPATIBILITY_VERSION': '1.0.0',
'DYLIB_CURRENT_VERSION': '111.1.4',
# Turn on stripping (yes, even in debug mode), and add the -c
# flag. This is what produces a stub library (MH_DYLIB_STUB)
# as opposed to a dylib (MH_DYLIB). MH_DYLIB_STUB files
# contain symbol tables and everything else needed for
# linking, but are stripped of section contents. This is the
# same way that the stub libraries in Mac OS X SDKs are
# created. dyld will refuse to load a stub library, so this
# provides some insurance in case anyone tries to load the
# stub at runtime.
'DEPLOYMENT_POSTPROCESSING': 'YES',
'STRIP_STYLE': 'non-global',
'STRIPFLAGS': '-c',
},
}, { # else: mac_sdk != "10.5"
# When using the 10.6 SDK or newer, the necessary definitions
# are already present in libSystem.dylib. There is no need to
# build a stub dylib to provide these symbols at link time. This
# target is still useful to cause those symbols to be treated as
# weak imports in dependents, who still must #include
# closure_blocks_leopard_compat.h to get weak imports.
'type': 'none',
}],
],
},
],
}],
],
} }
...@@ -1482,6 +1482,7 @@ ...@@ -1482,6 +1482,7 @@
'browser/intents/web_intents_registry_unittest.cc', 'browser/intents/web_intents_registry_unittest.cc',
'browser/internal_auth_unittest.cc', 'browser/internal_auth_unittest.cc',
'browser/language_usage_metrics_unittest.cc', 'browser/language_usage_metrics_unittest.cc',
'browser/mac/closure_blocks_leopard_compat_unittest.cc',
'browser/mac/keystone_glue_unittest.mm', 'browser/mac/keystone_glue_unittest.mm',
'browser/media/media_internals_unittest.cc', 'browser/media/media_internals_unittest.cc',
'browser/metrics/display_utils_unittest.cc', 'browser/metrics/display_utils_unittest.cc',
...@@ -2200,6 +2201,7 @@ ...@@ -2200,6 +2201,7 @@
# exist on disk so it can pull from it. # exist on disk so it can pull from it.
'dependencies': [ 'dependencies': [
'chrome', 'chrome',
'closure_blocks_leopard_compat',
'../third_party/ocmock/ocmock.gyp:ocmock', '../third_party/ocmock/ocmock.gyp:ocmock',
], ],
'include_dirs': [ 'include_dirs': [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment