Skip to content

Commit

Permalink
Add detox deployment script for Xcode projects
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoNatan committed Nov 4, 2016
1 parent d6552de commit 351d828
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@
[submodule "detox/ios/EarlGrey"]
path = detox/ios/EarlGrey
url = https://github.com/google/EarlGrey.git
[submodule "detox/scripts/Xcodeproj"]
path = detox/scripts/Xcodeproj
url = https://github.com/CocoaPods/Xcodeproj.git
[submodule "detox/scripts/Nanaimo"]
path = detox/scripts/Nanaimo
url = https://github.com/CocoaPods/Nanaimo.git
60 changes: 60 additions & 0 deletions detox/ios/Detox.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
objectVersion = 46;
objects = {

/* Begin PBXAggregateTarget section */
3941F4F21DC6200700F23DAC /* DetoxFramework */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 3941F4F31DC6200700F23DAC /* Build configuration list for PBXAggregateTarget "DetoxFramework" */;
buildPhases = (
3941F4F61DC6203000F23DAC /* ShellScript */,
);
dependencies = (
);
name = DetoxFramework;
productName = DetoxFramework;
};
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
3947679C1DBF985400D72256 /* Detox.h in Headers */ = {isa = PBXBuildFile; fileRef = 3947679A1DBF985400D72256 /* Detox.h */; settings = {ATTRIBUTES = (Public, ); }; };
394767AE1DBF987E00D72256 /* DetoxManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 394767A41DBF987E00D72256 /* DetoxManager.h */; };
Expand Down Expand Up @@ -316,6 +330,10 @@
LastUpgradeCheck = 0810;
ORGANIZATIONNAME = "Leo Natan";
TargetAttributes = {
3941F4F21DC6200700F23DAC = {
CreatedOnToolsVersion = 8.1;
ProvisioningStyle = Automatic;
};
394767961DBF985400D72256 = {
CreatedOnToolsVersion = 8.1;
ProvisioningStyle = Automatic;
Expand Down Expand Up @@ -345,6 +363,7 @@
projectRoot = "";
targets = (
394767961DBF985400D72256 /* Detox */,
3941F4F21DC6200700F23DAC /* DetoxFramework */,
);
};
/* End PBXProject section */
Expand Down Expand Up @@ -411,6 +430,22 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
3941F4F61DC6203000F23DAC /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal\n\n# make sure the output directory exists\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}\"\n\n# Step 1. Build Device and Simulator versions\nxcodebuild -target \"${PROJECT_NAME}\" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" clean build\nxcodebuild -target \"${PROJECT_NAME}\" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" clean build\n\n# Step 2. Copy the framework structure (from iphoneos build) to the universal folder\ncp -R \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework\" \"${UNIVERSAL_OUTPUTFOLDER}/\"\n\n# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory\nSIMULATOR_SWIFT_MODULES_DIR=\"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/.\"\nif [ -d \"${SIMULATOR_SWIFT_MODULES_DIR}\" ]; then\ncp -R \"${SIMULATOR_SWIFT_MODULES_DIR}\" \"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule\"\nfi\n\n# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory\nlipo -create -output \"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}\" \"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}\" \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}\"";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
394767921DBF985400D72256 /* Sources */ = {
isa = PBXSourcesBuildPhase;
Expand Down Expand Up @@ -446,6 +481,20 @@
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
3941F4F41DC6200700F23DAC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
3941F4F51DC6200700F23DAC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
3947679D1DBF985400D72256 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -550,6 +599,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Detox/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
Expand All @@ -567,6 +617,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Detox/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
Expand All @@ -579,6 +630,15 @@
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
3941F4F31DC6200700F23DAC /* Build configuration list for PBXAggregateTarget "DetoxFramework" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3941F4F41DC6200700F23DAC /* Debug */,
3941F4F51DC6200700F23DAC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
394767911DBF985400D72256 /* Build configuration list for PBXProject "Detox" */ = {
isa = XCConfigurationList;
buildConfigurations = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3941F4F21DC6200700F23DAC"
BuildableName = "DetoxFramework"
BlueprintName = "DetoxFramework"
ReferencedContainer = "container:Detox.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3941F4F21DC6200700F23DAC"
BuildableName = "DetoxFramework"
BlueprintName = "DetoxFramework"
ReferencedContainer = "container:Detox.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3941F4F21DC6200700F23DAC"
BuildableName = "DetoxFramework"
BlueprintName = "DetoxFramework"
ReferencedContainer = "container:Detox.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
2 changes: 1 addition & 1 deletion detox/ios/SocketRocket
3 changes: 2 additions & 1 deletion detox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"dependencies": {
"bplist-parser": "^0.1.1",
"lodash": "^4.14.1",
"mocha": "^2.5.3"
"mocha": "^2.5.3",
"xcode": "^0.8.9"
}
}
15 changes: 15 additions & 0 deletions detox/scripts/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Local File",
"type": "Ruby",
"request": "launch",
"cwd": "${workspaceRoot}",
"program": "${workspaceRoot}/deploy_detox.rb",
"args": [
"~/Desktop/detox-install_wip/DetoxDemoProject/DetoxDemoProject.xcodeproj"
]
}
]
}
1 change: 1 addition & 0 deletions detox/scripts/Nanaimo
Submodule Nanaimo added at 779af6
1 change: 1 addition & 0 deletions detox/scripts/Xcodeproj
Submodule Xcodeproj added at cc11c5
123 changes: 123 additions & 0 deletions detox/scripts/deploy_detox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env ruby

require 'pathname'

#Setup require path to include local Xcodeproj and Nanaimo submodules
$LOAD_PATH.unshift(Pathname.new(__FILE__).dirname + "Xcodeproj/lib")
$LOAD_PATH.unshift(Pathname.new(__FILE__).dirname + "Nanaimo/lib")

require 'xcodeproj'

def usage()
puts "Usage: deploy_detox.rb <path_to.xcodeproj>"
end

if ARGV.count != 1 then
usage
exit
end

project_path = Pathname.new(ARGV[0]).expand_path
project_path += ".xcodeproj" unless project_path.exist?
raise "Cannot find Xcode project" unless project_path.exist?

project_path_dir = project_path.dirname

puts "", "########################################", "Building Detox Framework", "########################################", ""

# raise "Detox framework build failed" unless system("xcodebuild build -project #{project_path_dir}/node_modules/detox/ios/Detox.xcodeproj -scheme DetoxFramework -configuration Release -derivedDataPath #{project_path_dir}/DetoxBuild", :out=>"/dev/null")

puts "", "########################################", "Integrating Detox Framework with Project", "########################################", ""

project = Xcodeproj::Project.open(project_path)

added_configs = []

project.build_configuration_list.build_configurations.each do |config|
next if config.name.include?('_Detox')

should_add = false
unless build_conf = project.build_configuration_list[config.name + '_Detox']
build_conf = project.new(Xcodeproj::Project::Object::XCBuildConfiguration)
should_add = true
end

build_conf.name = config.name + '_Detox'
build_conf.base_configuration_reference = config.base_configuration_reference.dup if config.base_configuration_reference
build_conf.build_settings = config.build_settings.dup if config.build_settings

added_configs << build_conf if should_add
end

added_configs.each { |config| project.build_configuration_list.build_configurations << config }

project.targets.each do |target|
if target.product_type == "com.apple.product-type.application" and target.platform_name == :ios and target.shell_script_build_phases.find { |script| script.name.nil? == false and script.name.include?("Detox") }.nil? then
script = target.new_shell_script_build_phase('Copy Detox Framework')
script.shell_path = '/bin/bash'
script.shell_script = "if [ -n \"$DEPLOY_DETOX_FRAMEWORK\" ]; then\nmkdir -p \"${BUILT_PRODUCTS_DIR}\"/\"${FRAMEWORKS_FOLDER_PATH}\"\ncp -r \"${PROJECT_DIR}\"/DetoxBuild/Build/Products/Release-universal/Detox.framework \"${BUILT_PRODUCTS_DIR}\"/\"${FRAMEWORKS_FOLDER_PATH}\"\nfi"
end

added_configs = []

target.build_configuration_list.build_configurations.each do |config|
next if config.name.include?('_Detox')

should_add = false
unless build_conf = target.build_configuration_list[config.name + '_Detox']
build_conf = project.new(Xcodeproj::Project::Object::XCBuildConfiguration)
should_add = true
end

build_conf.name = config.name + '_Detox'
build_conf.base_configuration_reference = config.base_configuration_reference.dup if config.base_configuration_reference
build_conf.build_settings = config.build_settings.dup if config.build_settings

if target.product_type == "com.apple.product-type.application" and target.platform_name == :ios then
search_paths = config.build_settings['FRAMEWORK_SEARCH_PATHS'].nil? ? ['$(inherited)'] : config.build_settings['FRAMEWORK_SEARCH_PATHS'].dup
unless search_paths.kind_of?(Array)
search_paths = [search_paths]
end
search_paths << '$(PROJECT_DIR)/DetoxBuild/Build/Products/Release-universal'
build_conf.build_settings['FRAMEWORK_SEARCH_PATHS'] = search_paths

other_linker_flags = config.build_settings['OTHER_LDFLAGS'].nil? ? ['$(inherited)'] : config.build_settings['OTHER_LDFLAGS'].dup if
unless other_linker_flags.kind_of?(Array)
other_linker_flags = [other_linker_flags]
end
other_linker_flags << '-framework'
other_linker_flags << 'Detox'
build_conf.build_settings['OTHER_LDFLAGS'] = other_linker_flags

build_conf.build_settings['COPY_DETOX_FRAMEWORK'] = 'YES'
end

added_configs << build_conf if should_add
end

added_configs.each { |config| target.build_configuration_list.build_configurations << config }
end

scheme_names = Xcodeproj::Project.schemes(project_path)
saved_schemes = 0

scheme_names.each do |scheme_name|
next if scheme_name.include?('_Detox')

#Try to open an existing shared scheme. If it failes, create a new scheme.
begin
scheme = Xcodeproj::XCScheme.new(Xcodeproj::XCScheme.shared_data_dir(project_path) + "#{scheme_name}.xcscheme")
#Ignore schemes for extensions
next unless scheme.launch_action.xml_element.attributes['launchAutomaticallySubstyle'].nil?
scheme.launch_action.build_configuration += '_Detox'
scheme.save_as(project_path, scheme_name + '_Detox', true)
saved_schemes += 1
rescue => exception
end
end

puts 'Error: No shared schemes found. Set at least one scheme as shared.' if saved_schemes == 0

project.save()

puts "", "########################################", "Done", "########################################", ""

0 comments on commit 351d828

Please sign in to comment.