Skip to content

Commit d3c460b

Browse files
author
runrevali
committed
Merge remote-tracking branch 'upstream/release-6.7.2' into feature-standalone_builder_inclusions
Conflicts: ide
2 parents e038c7e + 9cf41d8 commit d3c460b

File tree

9 files changed

+291
-50
lines changed

9 files changed

+291
-50
lines changed

docs/notes/bugfix-14422.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Binary submitted to App Store rejected due to minimum version mismatch

engine/src/deploy.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,60 @@ extern Boolean InitSSLCrypt(void);
8989

9090
////////////////////////////////////////////////////////////////////////////////
9191

92+
static const char *kMCDeployArchitectureStrings[] =
93+
{
94+
"",
95+
"i386",
96+
"x86-64",
97+
"armv6",
98+
"armv7",
99+
"armv7s",
100+
"arm64",
101+
"ppc",
102+
"ppc64",
103+
nil,
104+
};
105+
106+
static bool MCDeployMapArchitectureString(const MCString& p_string, MCDeployArchitecture& r_architecture)
107+
{
108+
for(uindex_t i = 0; kMCDeployArchitectureStrings[i] != nil; i++)
109+
{
110+
// As 'p_string' is an MCString the '==' operator does a caseless comparison.
111+
if (p_string == kMCDeployArchitectureStrings[i])
112+
{
113+
r_architecture = (MCDeployArchitecture)i;
114+
return true;
115+
}
116+
}
117+
118+
return false;
119+
}
120+
121+
static Exec_stat MCDeployPushMinOSVersion(MCDeployParameters& p_params, MCDeployArchitecture p_arch, const char *p_vers_string)
122+
{
123+
// Use sscanf to parse out the version string. We don't check the return value of
124+
// sscanf as we don't care - any malformed / missing components will come out as
125+
// 0.
126+
int t_major, t_minor, t_inc;
127+
t_major = t_minor = t_inc = 0;
128+
sscanf(p_vers_string, "%d.%d.%d", &t_major, &t_minor, &t_inc);
129+
130+
if (!MCMemoryResizeArray(p_params . min_os_version_count + 1, p_params . min_os_versions, p_params . min_os_version_count))
131+
return ES_ERROR;
132+
133+
uint32_t t_version;
134+
t_version = (t_major & 0xFFFF) << 16;
135+
t_version |= (t_minor & 0xFF) << 8;
136+
t_version |= (t_inc & 0xFF) << 0;
137+
138+
p_params . min_os_versions[p_params . min_os_version_count - 1] . architecture = p_arch;
139+
p_params . min_os_versions[p_params . min_os_version_count - 1] . version = t_version;
140+
141+
return ES_NORMAL;
142+
}
143+
144+
////////////////////////////////////////////////////////////////////////////////
145+
92146
static bool MCDeployWriteDefinePrologueSection(const MCDeployParameters& p_params, MCDeployCapsuleRef p_capsule)
93147
{
94148
MCCapsulePrologueSection t_prologue;
@@ -539,6 +593,52 @@ Exec_stat MCIdeDeploy::exec(MCExecPoint& ep)
539593
if (t_stat == ES_NORMAL && ep2 . getarray() != NULL)
540594
t_params . version_info = new MCVariableValue(*ep2 . getarray());
541595
}
596+
597+
// The 'min_os_version' is either a string or an array. If it is a string then
598+
// it encodes the version against the 'Unknown' architecture which is interpreted
599+
// by the deploy command to mean all architectures. Otherwise, the keys in the
600+
// array are assumed to be architecture names and each is pushed on the array.
601+
// If the 'min_os_version' is empty, then no change is brought to the binaries.
602+
// If multiple entries are present, then the 'unknown' mapping is used for any
603+
// architecture not explicitly specified. The current architecture strings that are
604+
// known are:
605+
// i386, x86-64, armv6, armv7, armv7s, arm64, ppc, ppc64
606+
// The empty string is taken to be 'unknown'.
607+
if (t_stat == ES_NORMAL)
608+
{
609+
t_stat = t_array -> fetch_element(ep2, "min_os_version");
610+
if (t_stat == ES_NORMAL)
611+
{
612+
if (ep2 . getformat() == VF_ARRAY)
613+
{
614+
MCExecPoint ep3(ep2);
615+
MCHashentry *t_entry;
616+
uindex_t t_index;
617+
t_entry = nil;
618+
t_index = 0;
619+
for(;;)
620+
{
621+
if (t_stat == ES_ERROR)
622+
break;
623+
624+
t_entry = ep2 . getarray() -> get_array() -> getnextelement(t_index, t_entry, False, ep);
625+
if (t_entry == nil)
626+
break;
627+
628+
MCDeployArchitecture t_arch;
629+
if (!MCDeployMapArchitectureString(t_entry -> string, t_arch))
630+
continue;
631+
632+
t_stat = t_entry -> value . fetch(ep3);
633+
634+
if (t_stat == ES_NORMAL)
635+
t_stat = MCDeployPushMinOSVersion(t_params, t_arch, ep3 . getcstring());
636+
}
637+
}
638+
else if (!ep2.isempty())
639+
t_stat = MCDeployPushMinOSVersion(t_params, kMCDeployArchitecture_Unknown, ep2 . getcstring());
640+
}
641+
}
542642

543643
// If platform is iOS and we are not Mac then error
544644
#ifndef _MACOSX
@@ -613,6 +713,7 @@ Exec_stat MCIdeDeploy::exec(MCExecPoint& ep)
613713
delete t_params . engine_ppc;
614714
delete t_params . engine_x86;
615715
delete t_params . version_info;
716+
MCMemoryDeleteArray(t_params . min_os_versions);
616717

617718
if (t_stat == ES_ERROR && t_soft_error)
618719
return ES_NORMAL;

engine/src/deploy.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
1919

2020
////////////////////////////////////////////////////////////////////////////////
2121

22+
enum MCDeployArchitecture
23+
{
24+
kMCDeployArchitecture_Unknown,
25+
kMCDeployArchitecture_I386,
26+
kMCDeployArchitecture_X86_64,
27+
kMCDeployArchitecture_ARMV6,
28+
kMCDeployArchitecture_ARMV7,
29+
kMCDeployArchitecture_ARMV7S,
30+
kMCDeployArchitecture_ARM64,
31+
kMCDeployArchitecture_PPC,
32+
kMCDeployArchitecture_PPC64,
33+
};
34+
35+
struct MCDeployMinOSVersion
36+
{
37+
// The architecture this version applies to.
38+
MCDeployArchitecture architecture;
39+
// The version word encoded as nibbles XXXX.YY.ZZ for X.Y.Z.
40+
uint32_t version;
41+
};
42+
2243
struct MCDeployParameters
2344
{
2445
// The path to the engine binaries to use. On Windows and Linux this should
@@ -32,6 +53,11 @@ struct MCDeployParameters
3253
// fields.
3354
MCVariableValue *version_info;
3455

56+
// When building for Mac/iOS, you can specify a min os version per arch
57+
// slice.
58+
MCDeployMinOSVersion *min_os_versions;
59+
uindex_t min_os_version_count;
60+
3561
// The root stackfile to be included in the standalone.
3662
char *stackfile;
3763
// The array of auxiliary stackfiles to be included in the standalone.

engine/src/deploy_macosx.cpp

Lines changed: 116 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ typedef uint32_t cpu_subtype_t;
100100
#define CPU_TYPE_MC98000 ((cpu_type_t) 10)
101101
#define CPU_TYPE_HPPA ((cpu_type_t) 11)
102102
#define CPU_TYPE_ARM ((cpu_type_t) 12)
103+
#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
103104
#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
104105
#define CPU_TYPE_SPARC ((cpu_type_t) 14)
105106
#define CPU_TYPE_I860 ((cpu_type_t) 15)
@@ -189,6 +190,30 @@ typedef uint32_t cpu_subtype_t;
189190
#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11)
190191
#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
191192

193+
/*
194+
* ARM subtypes
195+
*/
196+
#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0)
197+
#define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5)
198+
#define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6)
199+
#define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7)
200+
#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8)
201+
#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9)
202+
#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */
203+
#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */
204+
#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) /* Kirkwood40 */
205+
#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */
206+
#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */
207+
#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */
208+
209+
#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13)
210+
211+
/*
212+
* ARM64 subtypes
213+
*/
214+
#define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0)
215+
#define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1)
216+
192217
#define FAT_MAGIC 0xcafebabe
193218
#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
194219

@@ -862,6 +887,18 @@ struct dyld_info_command
862887
uint32_t export_size;
863888
};
864889

890+
/*
891+
* The version_min_command contains the min OS version on which this
892+
* binary was built to run.
893+
*/
894+
struct version_min_command {
895+
uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
896+
LC_VERSION_MIN_IPHONEOS */
897+
uint32_t cmdsize; /* sizeof(struct min_version_command) */
898+
uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
899+
uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
900+
};
901+
865902
////////////////////////////////////////////////////////////////////////////////
866903

867904
struct mach_32bit
@@ -963,6 +1000,11 @@ static void swap_relocation_info(bool p_to_network, relocation_info& x)
9631000
MCDeployByteSwapRecord(p_to_network, "ll", &x, sizeof(relocation_info));
9641001
}
9651002

1003+
static void swap_version_min_command(bool p_to_network, version_min_command& x)
1004+
{
1005+
MCDeployByteSwapRecord(p_to_network, "llll", &x, sizeof(version_min_command));
1006+
}
1007+
9661008
static void swap_load_command(bool p_to_network, uint32_t p_type, load_command* x)
9671009
{
9681010
switch(p_type)
@@ -998,7 +1040,12 @@ static void swap_load_command(bool p_to_network, uint32_t p_type, load_command*
9981040
swap_load_command_hdr(p_to_network, *x);
9991041
break;
10001042

1001-
default:
1043+
case LC_VERSION_MIN_MACOSX:
1044+
case LC_VERSION_MIN_IPHONEOS:
1045+
swap_version_min_command(p_to_network, *(version_min_command *)x);
1046+
break;
1047+
1048+
default:
10021049
swap_load_command_hdr(p_to_network, *x);
10031050
break;
10041051
}
@@ -1088,6 +1135,57 @@ static void relocate_function_starts_command(linkedit_data_command *x, int32_t p
10881135

10891136
////////////////////////////////////////////////////////////////////////////////
10901137

1138+
static bool MCDeployToMacOSXFetchMinOSVersion(const MCDeployParameters& p_params, mach_header& p_header, uint32_t& r_version)
1139+
{
1140+
// First work out what DeployArchitecture to look for.
1141+
MCDeployArchitecture t_arch;
1142+
if (p_header . cputype == CPU_TYPE_X86)
1143+
t_arch = kMCDeployArchitecture_I386;
1144+
else if (p_header . cputype == CPU_TYPE_X86_64)
1145+
t_arch = kMCDeployArchitecture_X86_64;
1146+
else if (p_header . cputype == CPU_TYPE_ARM && p_header . cpusubtype == CPU_SUBTYPE_ARM_V6)
1147+
t_arch = kMCDeployArchitecture_ARMV6;
1148+
else if (p_header . cputype == CPU_TYPE_ARM && p_header . cpusubtype == CPU_SUBTYPE_ARM_V7)
1149+
t_arch = kMCDeployArchitecture_ARMV7;
1150+
else if (p_header . cputype == CPU_TYPE_ARM && p_header . cpusubtype == CPU_SUBTYPE_ARM_V7S)
1151+
t_arch = kMCDeployArchitecture_ARMV7S;
1152+
else if (p_header . cputype == CPU_TYPE_ARM64)
1153+
t_arch = kMCDeployArchitecture_ARM64;
1154+
else if (p_header . cputype == CPU_TYPE_POWERPC)
1155+
t_arch = kMCDeployArchitecture_PPC;
1156+
else if (p_header . cputype == CPU_TYPE_POWERPC64)
1157+
t_arch = kMCDeployArchitecture_PPC64;
1158+
else
1159+
t_arch = kMCDeployArchitecture_Unknown;
1160+
1161+
// Search for both the architecture in the mach header and for the 'unknown'
1162+
// architecture. If the real arch is found, then we use that version; otherwise
1163+
// if there is an unknown arch then we use that version. If neither are found we
1164+
// return false which means the caller can do nothing.
1165+
int t_unknown_index, t_found_index;
1166+
t_unknown_index = -1;
1167+
t_found_index = -1;
1168+
for(uindex_t i = 0; i < p_params . min_os_version_count; i++)
1169+
if (p_params . min_os_versions[i] . architecture == t_arch &&
1170+
t_found_index < 0)
1171+
t_found_index = (signed)i;
1172+
else if (p_params . min_os_versions[i] . architecture == kMCDeployArchitecture_Unknown &&
1173+
t_unknown_index < 0)
1174+
t_unknown_index = (signed)i;
1175+
1176+
if (t_found_index < 0 && t_unknown_index < 0)
1177+
return false;
1178+
1179+
if (t_found_index >= 0)
1180+
{
1181+
r_version = p_params . min_os_versions[t_found_index] . version;
1182+
return true;
1183+
}
1184+
1185+
r_version = p_params . min_os_versions[t_unknown_index] . version;
1186+
return true;
1187+
}
1188+
10911189
template<typename T> bool MCDeployToMacOSXMainBody(const MCDeployParameters& p_params, bool p_big_endian, MCDeployFileRef p_engine, uint32_t p_engine_offset, uint32_t t_engine_size, uint32_t& x_offset, MCDeployFileRef p_output, mach_header& t_header, load_command **t_commands, uint32_t t_command_count)
10921190
{
10931191
bool t_success;
@@ -1240,7 +1338,7 @@ template<typename T> bool MCDeployToMacOSXMainBody(const MCDeployParameters& p_p
12401338
{
12411339
switch(t_commands[i] -> cmd)
12421340
{
1243-
// Relocate the commands we know about that contain file offset
1341+
// Relocate the commands we know about that contain file offset
12441342
case LC_SEGMENT:
12451343
relocate_segment_command<mach_32bit>((segment_command *)t_commands[i], t_file_delta, t_address_delta);
12461344
break;
@@ -1269,7 +1367,7 @@ template<typename T> bool MCDeployToMacOSXMainBody(const MCDeployParameters& p_p
12691367
relocate_function_starts_command((linkedit_data_command *)t_commands[i], t_file_delta, t_address_delta);
12701368
break;
12711369

1272-
// These commands have no file offsets
1370+
// These commands have no file offsets
12731371
case LC_UUID:
12741372
case LC_THREAD:
12751373
case LC_UNIXTHREAD:
@@ -1278,14 +1376,25 @@ template<typename T> bool MCDeployToMacOSXMainBody(const MCDeployParameters& p_p
12781376
case LC_LOAD_DYLINKER:
12791377
case LC_ENCRYPTION_INFO:
12801378
case LC_ENCRYPTION_INFO_64:
1281-
case LC_VERSION_MIN_MACOSX:
1282-
case LC_VERSION_MIN_IPHONEOS:
12831379
case LC_SOURCE_VERSION:
12841380
case LC_MAIN:
12851381
break;
12861382

1287-
// Any others that are present are an error since we don't know
1288-
// what to do with them.
1383+
// We rewrite the contents of these commands as appropriate to
1384+
// the 'min_os_versions' list in the params.
1385+
case LC_VERSION_MIN_MACOSX:
1386+
case LC_VERSION_MIN_IPHONEOS:
1387+
{
1388+
// Notice that we leave the SDK version alone - this is tied
1389+
// to linkage and so is probably unwise to adjust.
1390+
uint32_t t_version;
1391+
if (MCDeployToMacOSXFetchMinOSVersion(p_params, t_header, t_version))
1392+
((version_min_command *)t_commands[i]) -> version = t_version;
1393+
}
1394+
break;
1395+
1396+
// Any others that are present are an error since we don't know
1397+
// what to do with them.
12891398
default:
12901399
t_success = MCDeployThrow(kMCDeployErrorMacOSXUnknownLoadCommand);
12911400
break;

ide

Submodule ide updated from 7ebc40f to 9a7c66e

0 commit comments

Comments
 (0)