Skip to content

Commit

Permalink
Merge pull request #1 from um68/master
Browse files Browse the repository at this point in the history
Update for iOS and MacOS build
  • Loading branch information
KjellSchubert committed Feb 10, 2015
2 parents 50a21c9 + 45e8a57 commit 9f974f8
Show file tree
Hide file tree
Showing 60 changed files with 850 additions and 332 deletions.
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

0 comments on commit 9f974f8

Please sign in to comment.