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

Update for iOS and MacOS build #1

Merged
merged 21 commits into from
Feb 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dd6a107
started adding support for MacOS and iOS builds
um68 Jan 30, 2015
824fe18
fixed build dir for iOS/Mac release builds
um68 Jan 30, 2015
2ff96b2
added command line argument to specify targetPlatform (needed for Mac…
um68 Jan 30, 2015
11d3584
updated boost gyp files to exclude the executables for iOS builds
um68 Jan 30, 2015
466d920
fixed boost executable targets for none iOS builds (were disabled by …
um68 Feb 3, 2015
bf032a9
updated Xcode build settings for iOS/MacOS
um68 Feb 3, 2015
b162e6f
updated libraries to build on MacOS
um68 Feb 3, 2015
0bf4319
fixed print command
um68 Feb 3, 2015
3bfeb2c
openssl builds now for MacOS
um68 Feb 3, 2015
fa7b1db
zlib builds now for MacOS/iOS (required patch for includes)
um68 Feb 3, 2015
26ea993
updated compiler setting for iOS
um68 Feb 4, 2015
aa13659
updated compiler setting for iOS
um68 Feb 4, 2015
bd2957f
fixed openssl MacOS compile problem
um68 Feb 5, 2015
e91af3b
fixed xerces MacOS compile problem
um68 Feb 5, 2015
47821ad
fixed MacOS and iOS build settings
um68 Feb 5, 2015
0d2d287
added support for --targetPlatform flag for "brut install"
um68 Feb 5, 2015
d25c815
updated for compatibility with iOS and generic Xcode installation
um68 Feb 6, 2015
595fef5
added --targetPlatform for 'bru install' in order to support iOS
um68 Feb 6, 2015
cc4e554
updated libraries to compile for iOS/MacOS
Feb 10, 2015
42ca238
added directory where mac/ios executables are stored
Feb 10, 2015
45e8a57
new arguments to install and make are now optional
Feb 10, 2015
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
8 changes: 6 additions & 2 deletions bru.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def main():
parser_install = subparsers.add_parser('install')
parser_install.add_argument("installables", default = [], nargs = '*',
help = 'e.g. googlemock@1.7.0')
parser_install.add_argument('--targetPlatform', default='Native', required=False,
help = 'targetPlatform Native | iOS')

parser_test = subparsers.add_parser('test')
parser_test.add_argument("testables", default = [], nargs = '*',
Expand All @@ -42,13 +44,15 @@ def main():
help = 'config Debug | Release')
parser_make.add_argument('--verbose', '-v', default=0, action='count',
help = 'enables verbose output in underlying build toolchain (e.g. make)')
parser_make.add_argument('--targetPlatform', default='Native', required=False,
help = 'targetPlatform Native | iOS')

args = parser.parse_args()
library = get_library()
if args.command == 'install':
brulib.install.cmd_install(library, args.installables)
brulib.install.cmd_install(library, args.installables, args.targetPlatform)
elif args.command == 'make':
brulib.make.cmd_make(args.config, args.verbose)
brulib.make.cmd_make(args.config, args.verbose, args.targetPlatform)
elif args.command == 'test':
brulib.runtests.cmd_test(args.testables)
else:
Expand Down
7 changes: 6 additions & 1 deletion bru.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@

# http://unix.stackexchange.com/questions/17499/get-path-of-current-script-when-executed-through-a-symlink
# This is brittle & frowned upon, I might change this some time...
script_dir="$(dirname "$(readlink -f "$0")")"

if [ "$(uname)" == "Darwin" ]; then
script_dir="$(dirname "$(readlink "$0")")"
else
script_dir="$(dirname "$(readlink -f "$0")")"
fi
$script_dir/autoupdate.py --hours 24


# after the autoupdate run bru.py, forwarding all cmd line params
$script_dir/bru.py $@
48 changes: 45 additions & 3 deletions bru_common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@
["target_arch=='x64'", {
"msvs_configuration_platform": "x64",
}],
['OS=="mac"', {
'xcode_settings': {
'CLANG_CXX_LANGUAGE_STANDARD' : 'c++0x',
'CLANG_CXX_LIBRARY' : 'libc++',
'OTHER_CFLAGS' : '-Wno-c++11-narrowing -fvisibility=hidden',
}, # xcode_settings
}],
['OS=="iOS"', {
'xcode_settings': {
'SDKROOT': 'iphoneos',
'TARGETED_DEVICE_FAMILY': '1,2',
'CODE_SIGN_IDENTITY': 'iPhone Developer',
'IPHONEOS_DEPLOYMENT_TARGET': '6.0',
'ARCHS': '$(ARCHS_STANDARD_32_64_BIT) armv7s',
'CLANG_CXX_LANGUAGE_STANDARD' : 'c++0x',
'CLANG_CXX_LIBRARY' : 'libc++',
'OTHER_CFLAGS' : '-Wno-c++11-narrowing -fvisibility=hidden',
}, # xcode_settings
}]
],
"msvs_settings": {
"VCCLCompilerTool": {
Expand All @@ -49,7 +68,8 @@
},
},
"xcode_settings": {
"GCC_OPTIMIZATION_LEVEL": "0", #stop gyp from defaulting to - Os
"GCC_OPTIMIZATION_LEVEL ": "0", #stop gyp from defaulting to - Os
"CONFIGURATION_BUILD_DIR" : "../../lib/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"
},
},
"Release": {
Expand All @@ -69,7 +89,26 @@
"conditions": [
["target_arch=='x64'", {
"msvs_configuration_platform": "x64",
}]
}],
['OS=="mac"', {
'xcode_settings': {
'CLANG_CXX_LANGUAGE_STANDARD' : 'c++0x',
'CLANG_CXX_LIBRARY' : 'libc++',
'OTHER_CFLAGS' : '-Wno-c++11-narrowing -fvisibility=hidden',
}, # xcode_settings
}],
['OS=="iOS"', {
'xcode_settings': {
'SDKROOT': 'iphoneos',
'TARGETED_DEVICE_FAMILY': '1,2',
'CODE_SIGN_IDENTITY': 'iPhone Developer',
'IPHONEOS_DEPLOYMENT_TARGET': '6.0',
'ARCHS': '$(ARCHS_STANDARD_32_64_BIT) armv7s',
'CLANG_CXX_LANGUAGE_STANDARD' : 'c++0x',
'CLANG_CXX_LIBRARY' : 'libc++',
'OTHER_CFLAGS' : '-Wno-c++11-narrowing -fvisibility=hidden',
}, # xcode_settings
}]
],
"msvs_settings": {
"VCCLCompilerTool": {
Expand All @@ -83,6 +122,9 @@
"EnableIntrinsicFunctions": "true"
}
},
"xcode_settings": {
"CONFIGURATION_BUILD_DIR" : "../../lib/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"
},
"VCLibrarianTool": {
"AdditionalOptions": [
"/LTCG" # link time code generation
Expand All @@ -93,7 +135,7 @@
"OptimizeReferences": 2, # /OPT:REF
"EnableCOMDATFolding": 2, # /OPT:ICF
"LinkIncremental": 1 # disable incremental linking
}
},
}
},

Expand Down
31 changes: 23 additions & 8 deletions brulib/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import filecmp
import platform
import collections
import subprocess
import brulib.jsonc
import brulib.make
import brulib.module_downloader
Expand Down Expand Up @@ -184,8 +185,19 @@ def exec_make_command(formula, bru_modules_root, system):
make_commands = formula['make_command']
if not system in make_commands:
raise Exception("no key {} in make_command".format(system))

make_command = make_commands[system]

if system == 'iOS':
# xcode installation dir might vary -- we need to find the right location to pass to the config script
xcode_path=subprocess.check_output(['xcode-select', '-p'],universal_newlines=True).strip()
# the path that we need to pass to the config script depends on the latest supported iOS version of xcode
xcode_iOS=subprocess.check_output('xcodebuild -showsdks | grep iphoneos | cut -d " " -f 2', shell=True,universal_newlines=True).strip()
print ("Found xcode here: '{}'".format(xcode_path))
print ("iOS Version from xcode: '{}'".format(xcode_iOS))
# if the make command contains a placeholder for the xcode path and/or iOS version, we need to replace it.
make_command = make_command.replace("__BRU_XCODE__",xcode_path).replace("__BRU_IOS_VERSION__",xcode_iOS)

# On Windows msvs toolchain build tools are typically not in your
# PATH, but are expected to be added to your PATH via
# %VS110COMNTOOLS%\vsvars32.bat. Let's call this vsvars32.bat
Expand Down Expand Up @@ -219,12 +231,15 @@ def exec_make_command(formula, bru_modules_root, system):
raise ValueError("build failed with error code {}".format(error_code))
touch(make_done_file)

def download_module(library, module_name, module_version):
def download_module(library, module_name, module_version, targetPlatform):
bru_modules_root = "./bru_modules"
formula = library.load_formula(module_name, module_version)
brulib.module_downloader.get_urls(library, formula, bru_modules_root)
exec_make_command(formula, bru_modules_root, platform.system())

if targetPlatform == 'Native':
exec_make_command(formula, bru_modules_root, platform.system())
else:
exec_make_command(formula, bru_modules_root, targetPlatform)

def verify_resolved_dependencies(formula, target, resolved_dependencies):
""" param formula is the formula with a bunch of desired(!) dependencies
which after conflict resolution across the whole set of diverse deps
Expand Down Expand Up @@ -448,7 +463,7 @@ def resolve_conflicts(library, dependencies, root_requestor):
return [(module, resolved['version'], resolved['requestor'])
for (module, resolved) in recursive_deps.items()]

def install_from_bru_file(bru_filename, library):
def install_from_bru_file(bru_filename, library, targetPlatform):
""" this gets executed when you 'bru install': it looks for a *.bru file
in cwd and downloads the listed deps """
package_jso = brulib.jsonc.loadfile(bru_filename)
Expand All @@ -459,7 +474,7 @@ def install_from_bru_file(bru_filename, library):
print('processing dependency {} version {} requested by {}'
.format(module_name, module_version, requestor))
formula = library.load_formula(module_name, module_version)
download_module(library, module_name, module_version)
download_module(library, module_name, module_version, targetPlatform)
copy_gyp(library, formula, resolved_dependencies)

# copy common.gypi which is referenced by module.gyp files and usually
Expand Down Expand Up @@ -495,7 +510,7 @@ def install_from_bru_file(bru_filename, library):

# todo: clean up unused module dependencies from /bru_modules?

def cmd_install(library, installables):
def cmd_install(library, installables, targetPlatform="Native"):
""" param installables: e.g. [] or ['googlemock@1.7.0', 'boost-regex']
This is supposed to mimic 'npm install' syntax, see
https://docs.npmjs.com/cli/install. Examples:
Expand All @@ -518,7 +533,7 @@ def cmd_install(library, installables):
if bru_filename == None:
raise Exception("no file *.bru in cwd")
print('installing dependencies listed in', bru_filename)
install_from_bru_file(bru_filename, library)
install_from_bru_file(bru_filename, library, targetPlatform)
else:
# installables are ['googlemock', 'googlemock@1.7.0']
# In this case we simply add deps to the *.bru (and *.gyp) file in
Expand All @@ -537,4 +552,4 @@ def cmd_install(library, installables):
bru_filename, gyp_filename))
# now download the new dependency just like 'bru install' would do
# after we added the dep to the bru & gyp file:
install_from_bru_file(bru_filename, library)
install_from_bru_file(bru_filename, library, targetPlatform)
92 changes: 88 additions & 4 deletions brulib/make.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import platform
import brulib.install

def cmd_make(config, verbose):
def cmd_make(config, verbose, targetPlatform="Native"):
""" this command makes some educated guesses about which toolchain
the user probably wants to run, then invokes gyp to create the
makefiles for this toolchain and invokes the build. On Linux
Expand All @@ -25,7 +25,7 @@ def cmd_make(config, verbose):
param verbose 0 means not verbose, >= 1 means higher verbosity level
(whatever that means in the underlying toolchain)
"""
print("running 'bru make --config {}'".format(config))
print("running 'bru make --config {} --targetPlatform {}'".format(config,targetPlatform))

# first locate the single gyp in the cwd
bru_file = brulib.install.get_single_bru_file('.')
Expand All @@ -39,9 +39,25 @@ def cmd_make(config, verbose):

system = platform.system()
if system == 'Windows':
cmd_make_win(gyp_file, config)
if targetPlatform == 'Native':
cmd_make_win(gyp_file, config)
else:
raise Exception('targetPlatform {} not supported on platform {}'\
.format(targetPlatform, system))
elif system == 'Linux':
cmd_make_linux(gyp_file, config, verbose)
if targetPlatform == 'Native':
cmd_make_linux(gyp_file, config, verbose)
else:
raise Exception('targetPlatform {} not supported on platform {}'\
.format(targetPlatform, system))
elif system == 'Darwin':
if targetPlatform == 'iOS':
cmd_make_ios(gyp_file, config, verbose)
elif targetPlatform == 'Native':
cmd_make_macos(gyp_file, config, verbose)
else:
raise Exception('targetPlatform {} not supported on platform {}'\
.format(targetPlatform, system))
else:
raise Exception('no idea how to invoke gyp & toolchain on platform {}'\
.format(system))
Expand Down Expand Up @@ -167,3 +183,71 @@ def cmd_make_linux(gyp_filename, config, verbose):
if returncode != 0:
raise Exception('Build failed: make returned', returncode)
print('Build complete.')

def cmd_make_macos(gyp_filename, config, verbose):
# Here we could check if ninja or some such is installed to generate ninja
# project files. But for simplicity's sake let's just use whatever gyp
# defaults to.

# For some odd reason passing './package.gyp' as a param to gyp will
# generate garbage, instead you gotta pass 'package.gyp'. Se let's
# explicitly remove a leading ./
dirname = os.path.dirname(gyp_filename)
assert dirname == '.' or len(dirname) == 0
gyp_filename = os.path.basename(gyp_filename)
gyp_cmdline = 'gyp --depth=. -f xcode {} --generator-output=./xcode-macos'.format(gyp_filename)
run_gyp(gyp_cmdline)
filepattern = './xcode-macos/*.xcodeproj'
files = glob.glob(filepattern)
print(filepattern)
print(files)
if len(files) == 0:
raise Exception('gyp did not generate {}, no idea how to '
'build with your toolchain, please build manually').format(filepattern)
xcode_cmdline = 'xCodeBuild -alltargets -project {} -configuration {}'.format(files[0],config)
print("running '{}'".format(xcode_cmdline))
returncode = os.system(xcode_cmdline)
if returncode != 0:
raise Exception('Build failed: make returned', returncode)
print('Build complete.')

def cmd_make_ios(gyp_filename, config, verbose):
# Here we could check if ninja or some such is installed to generate ninja
# project files. But for simplicity's sake let's just use whatever gyp
# defaults to.

# For some odd reason passing './package.gyp' as a param to gyp will
# generate garbage, instead you gotta pass 'package.gyp'. Se let's
# explicitly remove a leading ./
dirname = os.path.dirname(gyp_filename)
assert dirname == '.' or len(dirname) == 0
gyp_filename = os.path.basename(gyp_filename)
gyp_cmdline = 'gyp --depth=. -f xcode -DOS=iOS {} --generator-output=./xcode-ios'.format(gyp_filename)
run_gyp(gyp_cmdline)

filepattern = './xcode-ios/*.xcodeproj'
files = glob.glob(filepattern)
if len(files) == 0:
raise Exception('gyp did not generate {}, no idea how to '
'build with your toolchain, please build manually').format(filepattern)
xcode_cmdline = 'xCodeBuild -alltargets -project {} -configuration {} -sdk iphonesimulator'.format(files[0],config)
print("running '{}'".format(xcode_cmdline))
returncode = os.system(xcode_cmdline)
if returncode != 0:
raise Exception('Build failed: make for device returned', returncode)
xcode_cmdline = 'xCodeBuild -alltargets -project {} -configuration {} -sdk iphoneos'.format(files[0],config)
print("running '{}'".format(xcode_cmdline))
returncode = os.system(xcode_cmdline)
if returncode != 0:
raise Exception('Build failed: make for simulator returned', returncode)
mkdir_cmdline = 'mkdir lib/{}-Universial'.format(config)
returncode = os.system(mkdir_cmdline)
filepattern = './lib/{}-iphoneos/lib*.a'.format(config)
for file in glob.glob(filepattern):
name = os.path.basename(os.path.normpath(file))
command = 'lipo -create lib/{}-iphoneos/{} lib/{}-iphonesimulator/{} -output lib/{}-Universial/{}'.format(config,name,config,name,config,name)
print("running '{}'".format(command))
returncode = os.system(command)
if returncode != 0:
raise Exception('Build failed: lipo returned', returncode)
print('Build complete.')
1 change: 1 addition & 0 deletions brulib/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def locate_executable(target_name):
"""
for config in ['Release', 'Debug']:
candidates = [
os.path.join('lib', config, target_name),
os.path.join('out', config, target_name),
os.path.join('out', config, target_name + '.exe'),
os.path.join(config, target_name),
Expand Down
10 changes: 6 additions & 4 deletions library/boost-algorithm/1.57.0.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
"../boost-exception/boost-exception.gyp:*",
"../boost-iterator/boost-iterator.gyp:*"
]
},
}
],

"conditions": [
["OS!='iOS'", {

{
"target_name": "boost-algorithm_partition_copy_test1",
"type": "executable",
"test": {},
Expand All @@ -41,7 +44,6 @@
"boost-algorithm",
"../boost-test/boost-test.gyp:*"
]
}

}]
]
}
12 changes: 8 additions & 4 deletions library/boost-any/1.57.0.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@
"../boost-mpl/boost-mpl.gyp:*",
"../boost-type_index/boost-type_index.gyp:*"
]
},

}
],
"conditions": [
["OS!='iOS'",
{
"target_name": "boost-any_test",
"type": "executable",
"test": {},
"sources": [
"1.57.0/any-boost-1.57.0/test/any_test.cpp"
],
"dependencies": [ "boost-any" ]
"dependencies": [ "boost-any"
]
}
]
]
}
}
Loading