Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit b597e48

Browse files
committed
[[ ModuleAssemblies ]] Fix extension functionality for multi-module assemblies
A single lcm bytecode file can be an assembly of multiple module files. This patch adjusts the extensions API, the extension builder's packager and module compilation to account for this possibility. We also relax the restriction on a single source file per extension folder to account for the possibility of multi-module extensions.
1 parent 771cdda commit b597e48

3 files changed

Lines changed: 122 additions & 55 deletions

File tree

Toolset/libraries/revidedeveloperextensionlibrary.livecodescript

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -162,40 +162,36 @@ function revIDEDeveloperExtensions
162162
return tExtensionDetailsA
163163
end revIDEDeveloperExtensions
164164

165-
private command __revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, @rFile, @rType
166-
local tExtFile, tType
167-
revIDEExtensionFetchSourceFromFolder pFolder, tExtFile, tType
165+
private command __revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, @rFile, @rSupportFiles, @rType
166+
local tMainFile, tType, tSupportFiles
167+
revIDEExtensionFetchSourceFromFolder pFolder, tMainFile, tSupportFiles, tType
168168

169-
local tNumExtensions
170-
put the number of lines in tExtFile into tNumExtensions
171-
172-
# If there are multiple lcb files in one folder, it's an error.
173-
if tNumExtensions > 1 then
174-
put replaceText(tExtFile, return, ",") into tExtFile
175-
__revIDEDeveloperExtensionSendError "multiple lcb files in folder" && pFolder & ":" && tExtFile
176-
return empty
169+
if the result is not empty then
170+
__revIDEDeveloperExtensionSendError the result
177171
end if
178172

179-
put tExtFile into rFile
173+
put tMainFile into rFile
174+
put tSupportFiles into rSupportFiles
180175
put tType into rType
181176
end __revIDEDeveloperExtensionFetchExtensionSourceInFolder
182177

183178
function revIDEDeveloperExtensionNoCompile pFolder
184-
local tFile, tType
185-
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tType
179+
local tFile, tType, tSupportFiles
180+
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tSupportFiles, tType
186181

187182
if tFile is empty then
188183
return empty
189184
end if
190185

191186
if tType is "lcs" then
192-
return __revIDEDeveloperExtensionDetailsFromFile(pFolder, tFile, tType)
187+
return __revIDEDeveloperExtensionDetailsFromFile(pFolder, tFile, tSupportFiles, tType)
193188
end if
194189

195190
local tDataA
196191
revIDEExtensionMetadata pFolder, tFile, tType, tDataA
197192
if the result is not empty then
198193
put tFile into tDataA["file"]
194+
put tSupportFiles into tDataA["support_files"]
199195
end if
200196
return tDataA
201197
end revIDEDeveloperExtensionNoCompile
@@ -217,14 +213,14 @@ command revIDEDeveloperExtensionsActiveFolders pFolders
217213
end revIDEDeveloperExtensionsActiveFolders
218214

219215
function revIDEDeveloperExtension pFolder
220-
local tFile, tType
221-
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tType
216+
local tFile, tType, tSupportFiles
217+
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tSupportFiles, tType
222218

223219
if tFile is empty then
224220
return empty
225221
end if
226222

227-
return __revIDEDeveloperExtensionDetailsFromFile(pFolder, tFile, tType)
223+
return __revIDEDeveloperExtensionDetailsFromFile(pFolder, tFile, tSupportFiles, tType)
228224
end revIDEDeveloperExtension
229225

230226
private function __revIDEDeveloperExtensionFetchFolderDetails pFolder, pFile
@@ -360,11 +356,12 @@ private function __revIDEDeveloperExtensionListResourcesRecursive pFolder, pPref
360356
return tResources
361357
end __revIDEDeveloperExtensionListResourcesRecursive
362358

363-
private function __revIDEDeveloperExtensionDetailsFromFile pFolder, pFile, pType
359+
private function __revIDEDeveloperExtensionDetailsFromFile pFolder, pFile, pSupportFiles, pType
364360
local tDetailsA
365361
put __revIDEDeveloperExtensionFetchFolderDetails(pFolder, pFile) into tDetailsA
366362

367-
put pFile into tDetailsA["file"]
363+
put pFile into tDetailsA["file"]
364+
put pSupportFiles into tDetailsA["support_files"]
368365
if pType is "lcb" then
369366
if not __revIDEDeveloperExtensionShouldRecompile(pFolder, pFile) then
370367

@@ -380,7 +377,7 @@ private function __revIDEDeveloperExtensionDetailsFromFile pFolder, pFile, pType
380377
else
381378
# The compiled module or manifest is not up to date, so compile.
382379
__revIDEDeveloperExtensionLog "Compiling module" && pFolder & slash & pFile
383-
__revIDEDeveloperCompileModule pFolder & slash & pFile, pFolder
380+
__revIDEDeveloperCompileModule pFolder & slash & pFile, pSupportFiles, pFolder
384381
if the result is not empty then
385382
# This may be better as a warning, and try to parse info direct from the file.
386383
__revIDEDeveloperExtensionSendError the result
@@ -681,8 +678,8 @@ private command __revIDEDeveloperExtensionEditLCBScript pFile
681678
end __revIDEDeveloperExtensionEditLCBScript
682679

683680
on revIDEDeveloperExtensionOpen pFolder
684-
local tFile, tType
685-
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tType
681+
local tFile, tType, tSupportFiles
682+
__revIDEDeveloperExtensionFetchExtensionSourceInFolder pFolder, tFile, tSupportFiles, tType
686683
if tFile is empty then
687684
exit revIDEDeveloperExtensionOpen
688685
end if
@@ -737,8 +734,8 @@ private function __fetchMetadatum pXmlId, pKey
737734
return textDecode(revXMLNodeContents(pXmlId, tNode), "utf-8")
738735
end __fetchMetadatum
739736

740-
private command __revIDEDeveloperCompileModule pFile, pTargetFolder
741-
revIDEExtensionCompile pFile, pTargetFolder
737+
private command __revIDEDeveloperCompileModule pFile, pSupportFiles, pTargetFolder
738+
revIDEExtensionCompile pFile, pSupportFiles, pTargetFolder
742739

743740
if the result is not empty then
744741
__revIDEDeveloperCompilationError the result
@@ -892,9 +889,12 @@ private command __revIDEDeveloperExtensionBuildPackage pFolder, pTargetFolder, @
892889
put empty into tEditors
893890
end if
894891

892+
local tSupportFiles
893+
put tDetailsA["support_files"] into tSupportFiles
894+
895895
if tError is empty then
896896
put __revIDEDeveloperExtensionAddSpecifiedFilesToPackage(\
897-
tFullPath, pFolder, tArchive, pFolder & slash & "module.lcm", \
897+
tFullPath, tSupportFiles, pFolder, tArchive, pFolder & slash & "module.lcm", \
898898
tIcon, tRetinaIcon, tGuide, tDocs, tResources, tCode, \
899899
tSamples, tInterfaceFile, tDefaultScript, tEditors) \
900900
into tError
@@ -918,10 +918,10 @@ private command __revIDEDeveloperExtensionBuildPackage pFolder, pTargetFolder, @
918918
end __revIDEDeveloperExtensionBuildPackage
919919

920920
private function __revIDEDeveloperExtensionAddSpecifiedFilesToPackage \
921-
pSource, pFolder, pArchive, pModule, pIcon, pRetinaIcon, pGuide, \
922-
pDocs, pResourcesFolder, pCodeFolder, pSamplesFolder, \
923-
pInterfaceFile, pDefaultScript, pEditors
924-
921+
pSource, pSupportFiles, pFolder, pArchive, pModule, pIcon, \
922+
pRetinaIcon, pGuide, pDocs, pResourcesFolder, pCodeFolder, \
923+
pSamplesFolder, pInterfaceFile, pDefaultScript, pEditors
924+
925925
local tError
926926

927927
set the itemdelimiter to slash
@@ -932,6 +932,16 @@ private function __revIDEDeveloperExtensionAddSpecifiedFilesToPackage \
932932
put "couldn't add source" into tError
933933
end if
934934

935+
# Add support files into package
936+
repeat for each line tSupport in pSupportFiles
937+
put pFolder & slash & tSupport into tSupport
938+
revZipAddItemWithFile pArchive, item -1 of tSupport, tSupport
939+
940+
if the result begins with "ziperr" then
941+
put "couldn't add support file" && tSupport into tError
942+
end if
943+
end repeat
944+
935945
# Add module into package
936946
revZipAddItemWithFile pArchive, "module.lcm", pModule
937947

@@ -951,10 +961,10 @@ private function __revIDEDeveloperExtensionAddSpecifiedFilesToPackage \
951961
# Add user guide
952962
if tError is empty then
953963
// AL-2015-03-03: [[ Bug 14781 ]] If there is no guide, warn and don't try to add a file
954-
if pGuide is empty then
955-
__revIDEDeveloperExtensionSendWarning "no user guide found"
956-
else
957-
revZipAddItemWithFile pArchive, "docs/guide/guide.md", pGuide
964+
if pGuide is empty then
965+
__revIDEDeveloperExtensionSendWarning "no user guide found"
966+
else
967+
revZipAddItemWithFile pArchive, "docs/guide/guide.md", pGuide
958968
end if
959969
if the result begins with "ziperr" then
960970
put "couldn't add guide" into tError

Toolset/libraries/revideextensionlibrary.livecodescript

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -908,41 +908,72 @@ function revIDEExtensionsOrderByDependency pExtensions
908908
return __dependencyOrder(tDependencies, pExtensions)
909909
end revIDEExtensionsOrderByDependency
910910

911-
command revIDEExtensionFetchSourceFromFolder pFolder, @rSource, @rType
911+
private function __RegexPatternForSource pType
912+
switch pType
913+
case "lcb"
914+
return "^.*\.lcb$"
915+
break
916+
case "lcs"
917+
return "^.*\.livecode(script)?$"
918+
break
919+
end switch
920+
end __RegexPatternForSource
921+
922+
command revIDEExtensionFetchSourceFromFolder pFolder, @rSource, @rSupportFiles, @rType
912923
local tFiles
913924
put files(pFolder) into tFiles
914925

915-
local tExtFile, tType
916-
filter tFiles with "*.lcb" into tExtFile
926+
local tExtFiles, tType
927+
filter tFiles with regex pattern \
928+
__RegexPatternForSource("lcb") into tExtFiles
917929
if there is a file (pFolder & slash & "module.lcm") \
918-
or tExtFile is not empty then
930+
or tExtFiles is not empty then
919931
put "lcb" into tType
920932
end if
933+
921934
if tType is empty then
922-
filter tFiles with regex pattern ".*\.livecode(script)?$" into tExtFile
923-
if tExtFile is not empty then
935+
filter tFiles with regex pattern \
936+
__RegexPatternForSource("lcs") into tExtFiles
937+
if tExtFiles is not empty then
924938
put "lcs" into tType
925939
end if
926940
end if
927941

942+
-- Try and separate main source from support
943+
local tFoundCount, tSupport, tMainFile
944+
put the number of lines in tExtFiles into tFoundCount
945+
if tFoundCount > 1 then
946+
set the itemdelimiter to "."
947+
repeat for each line tTry in tExtFiles
948+
filter tExtFiles with item 1 to -2 of tTry & "-*" into tSupport
949+
if the number of lines in tSupport is tFoundCount - 1 then
950+
put tTry into tMainFile
951+
exit repeat
952+
end if
953+
put empty into tSupport
954+
end repeat
955+
if tSupport is empty then
956+
return "Invalid extension folder" && pFolder & return & \
957+
"Must have one main module, with all support modules named" && \
958+
"<main-name>-<support-name>."
959+
end if
960+
else
961+
put tExtFiles into tMainFile
962+
end if
963+
928964
if tType is empty then
929965
put "none" into tType
930966
end if
931967

932-
put tExtFile into rSource
968+
put tMainFile into rSource
969+
put tSupport into rSupportFiles
933970
put tType into rType
971+
return empty
934972
end revIDEExtensionFetchSourceFromFolder
935973

936974
private command __FindExtensionsInFolderRecursive pFolder, pIsUserFolder, @xDataA
937-
local tExtSource, tArray, tFiles, tExtFile, tType
938-
revIDEExtensionFetchSourceFromFolder pFolder, tExtFile, tType
939-
940-
local tNumExtensions
941-
put the number of lines in tExtFile into tNumExtensions
942-
if tNumExtensions > 1 then
943-
get __revIDEError("Invalid extension folder" && pFolder & ": require exactly one extension per folder")
944-
exit __FindExtensionsInFolderRecursive
945-
end if
975+
local tExtSource, tArray, tFiles, tMainSource, tSupportFiles, tType
976+
revIDEExtensionFetchSourceFromFolder pFolder, tMainSource, tSupportFiles, tType
946977

947978
-- If we found no extensions, recurse
948979
if tType is "none" then
@@ -955,12 +986,13 @@ private command __FindExtensionsInFolderRecursive pFolder, pIsUserFolder, @xData
955986
end if
956987

957988
if tType is "lcb" then
958-
put __fetchModuleData(pFolder, tExtFile) into tArray
989+
put __fetchModuleData(pFolder, tMainSource) into tArray
959990
else
960-
put __fetchScriptLibraryData(pFolder, tExtFile) into tArray
991+
put __fetchScriptLibraryData(pFolder, tMainSource) into tArray
961992
end if
962993

963-
put tExtFile into tArray["source_file"]
994+
put tMainSource into tArray["source_file"]
995+
put tSupportFiles into tArray["support_files"]
964996
put tType into tArray["source_type"]
965997
put not pIsUserFolder into tArray["ide"]
966998

@@ -1201,6 +1233,8 @@ private command __revIDELCBExtensionLoad pID, pFolder, pVersion, pStatus, \
12011233
__extensionPropertySet tCacheIndex, "install_path", pFolder
12021234
end if
12031235

1236+
local tSupportFiles
1237+
put pAdditionalInfoA["support_files"] into tSupportFiles
12041238
local tLoadOnStartup
12051239
if pError is empty then
12061240
put revIDEExtensionGetLoadOnStartup(pID) into tLoadOnStartup
@@ -1210,7 +1244,7 @@ private command __revIDELCBExtensionLoad pID, pFolder, pVersion, pStatus, \
12101244
-- If we have an error loading, try to recompile the extension
12111245
if pError is not empty then
12121246
if not pIsIDEExtension and pSourceFile is not empty then
1213-
revIDEExtensionCompile pFolder & slash & pSourceFile, pFolder
1247+
revIDEExtensionCompile pFolder & slash & pSourceFile, tSupportFiles, pFolder
12141248
if the result is empty then
12151249
local tNewError
12161250
__LoadExtension tCacheIndex, "lcb", pSourceFile, pFolder, pStatus, tNewError
@@ -1228,6 +1262,7 @@ private command __revIDELCBExtensionLoad pID, pFolder, pVersion, pStatus, \
12281262
__extensionPropertySet tCacheIndex, "ide", pIsIDEExtension
12291263
__extensionPropertySet tCacheIndex, "source_file", pSourceFile
12301264
__extensionPropertySet tCacheIndex, "source_type", "lcb"
1265+
__extensionPropertySet tCacheIndex, "support_files", tSupportFiles
12311266

12321267
# Check for sample stacks
12331268
__extensionPropertySet tCacheIndex, "samples", __extensionSampleStacks(pID,pFolder)
@@ -1337,6 +1372,7 @@ private command __revIDELCSExtensionLoad pFullPath, pFolder, pVersion, pStatus,
13371372
__extensionPropertySet tCacheIndex, "source_type", "lcs"
13381373
__extensionPropertySet tCacheIndex, "type", "library"
13391374
__extensionPropertySet tCacheIndex, "uservisible", true
1375+
__extensionPropertySet tCacheIndex, "support_files", pAdditionalInfoA["support_files"]
13401376

13411377
# Store the extension's property metadata
13421378
-- revIDEExtensionSetInfo pID
@@ -1598,7 +1634,7 @@ private function shellFormat pArg, pSwitch
15981634
return tOutput & quote & pArg & quote & " "
15991635
end shellFormat
16001636

1601-
command revIDEExtensionCompile pFile, pTargetFolder
1637+
command revIDEExtensionCompile pFile, pSupportFiles, pTargetFolder
16021638
# The manifest is currently always generated from the source
16031639
if there is a file (pTargetFolder & slash & "manifest.xml") then
16041640
delete file (pTargetFolder & slash & "manifest.xml")
@@ -1623,6 +1659,11 @@ command revIDEExtensionCompile pFile, pTargetFolder
16231659
# The output
16241660
put shellFormat(pTargetFolder & slash & "module.lcm", "output") after tShellCommand
16251661

1662+
# Support files must be dependency-ordered
1663+
repeat for each line tSupport in revIDEExtensionsOrderByDependency(pSupportFiles)
1664+
put shellFormat(pTargetFolder & slash &tSupport) after tShellCommand
1665+
end repeat
1666+
16261667
# The target .lcb file
16271668
put shellFormat(pFile) after tShellCommand
16281669

notes/bugfix-20862.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Fix multi-module assembly support
2+
The extension builder now supports multi-module assemblies properly.
3+
An extension folder can contain a main module, eg main.lcb, and any
4+
number of support modules, named <main name>-<suffix>.lcb, which are
5+
then compiled together into one bytecode file.
6+
7+
For example, it is useful when building cross-platform extensions to
8+
put the platform-specific code in a support module, so the extension
9+
folder would contain for example
10+
11+
button.lcb
12+
button-android.lcb
13+
button-ios.lcb
14+
...
15+
etc
16+

0 commit comments

Comments
 (0)