diff options
20 files changed, 991 insertions, 154 deletions
diff --git a/doc/reference/modules/bundle-module.qdoc b/doc/reference/modules/bundle-module.qdoc index 92b51029a..956d8fe8b 100644 --- a/doc/reference/modules/bundle-module.qdoc +++ b/doc/reference/modules/bundle-module.qdoc @@ -293,4 +293,19 @@ \li Path of the bundle's Versions subdirectory. This is only relevant for (non-shallow) framework bundles. \endtable + + \section1 Relevant File Tags + + \table + \header + \li Tag + \li Auto-tagged File Names + \li Since + \li Description + \row + \li \c{"bundle.content"} + \li - + \li 1.8 + \li This tag is attached to the output artifacts of the rule that produces the bundle. + \endtable */ diff --git a/examples/install-bundle/MainMenu.xib b/examples/install-bundle/MainMenu.xib new file mode 100644 index 000000000..14312411a --- /dev/null +++ b/examples/install-bundle/MainMenu.xib @@ -0,0 +1,680 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6157" systemVersion="14A237a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6157"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="NSApplication"> + <connections> + <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application"/> + <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider=""> + <connections> + <outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/> + </connections> + </customObject> + <customObject id="YLy-65-1bz" customClass="NSFontManager"/> + <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6"> + <items> + <menuItem title="CocoaApp" id="1Xt-HY-uBw"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="CocoaApp" systemMenu="apple" id="uQy-DD-JDr"> + <items> + <menuItem title="About CocoaApp" id="5kV-Vb-QxS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/> + <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/> + <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/> + <menuItem title="Services" id="NMo-om-nkz"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/> + </menuItem> + <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/> + <menuItem title="Hide CocoaApp" keyEquivalent="h" id="Olw-nP-bQN"> + <connections> + <action selector="hide:" target="-1" id="PnN-Uc-m68"/> + </connections> + </menuItem> + <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/> + </connections> + </menuItem> + <menuItem title="Show All" id="Kd2-mp-pUS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/> + <menuItem title="Quit CocoaApp" keyEquivalent="q" id="4sb-4s-VLi"> + <connections> + <action selector="terminate:" target="-1" id="Te7-pn-YzF"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="File" id="dMs-cI-mzQ"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="File" id="bib-Uj-vzu"> + <items> + <menuItem title="New" keyEquivalent="n" id="Was-JA-tGl"> + <connections> + <action selector="newDocument:" target="-1" id="4Si-XN-c54"/> + </connections> + </menuItem> + <menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9"> + <connections> + <action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/> + </connections> + </menuItem> + <menuItem title="Open Recent" id="tXI-mr-wws"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ"> + <items> + <menuItem title="Clear Menu" id="vNY-rz-j42"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="m54-Is-iLE"/> + <menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG"> + <connections> + <action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/> + </connections> + </menuItem> + <menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV"> + <connections> + <action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/> + </connections> + </menuItem> + <menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A"> + <connections> + <action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/> + </connections> + </menuItem> + <menuItem title="Revert to Saved" id="KaW-ft-85H"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="aJh-i4-bef"/> + <menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK"> + <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/> + <connections> + <action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/> + </connections> + </menuItem> + <menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS"> + <connections> + <action selector="print:" target="-1" id="qaZ-4w-aoO"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Edit" id="5QF-Oa-p0T"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Edit" id="W48-6f-4Dl"> + <items> + <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg"> + <connections> + <action selector="undo:" target="-1" id="M6e-cu-g7V"/> + </connections> + </menuItem> + <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam"> + <connections> + <action selector="redo:" target="-1" id="oIA-Rs-6OD"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/> + <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG"> + <connections> + <action selector="cut:" target="-1" id="YJe-68-I9s"/> + </connections> + </menuItem> + <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU"> + <connections> + <action selector="copy:" target="-1" id="G1f-GL-Joy"/> + </connections> + </menuItem> + <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL"> + <connections> + <action selector="paste:" target="-1" id="UvS-8e-Qdg"/> + </connections> + </menuItem> + <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/> + </connections> + </menuItem> + <menuItem title="Delete" id="pa3-QI-u2k"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/> + </connections> + </menuItem> + <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m"> + <connections> + <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/> + <menuItem title="Find" id="4EN-yA-p0u"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Find" id="1b7-l0-nxx"> + <items> + <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/> + </connections> + </menuItem> + <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/> + </connections> + </menuItem> + <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/> + </connections> + </menuItem> + <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/> + </connections> + </menuItem> + <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/> + </connections> + </menuItem> + <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd"> + <connections> + <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Spelling" id="3IN-sU-3Bg"> + <items> + <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI"> + <connections> + <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/> + </connections> + </menuItem> + <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7"> + <connections> + <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/> + <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/> + </connections> + </menuItem> + <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/> + </connections> + </menuItem> + <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Substitutions" id="9ic-FL-obx"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Substitutions" id="FeM-D8-WVr"> + <items> + <menuItem title="Show Substitutions" id="z6F-FW-3nz"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/> + <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/> + </connections> + </menuItem> + <menuItem title="Smart Quotes" id="hQb-2v-fYv"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/> + </connections> + </menuItem> + <menuItem title="Smart Dashes" id="rgM-f4-ycn"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/> + </connections> + </menuItem> + <menuItem title="Smart Links" id="cwL-P1-jid"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/> + </connections> + </menuItem> + <menuItem title="Data Detectors" id="tRr-pd-1PS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/> + </connections> + </menuItem> + <menuItem title="Text Replacement" id="HFQ-gK-NFA"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Transformations" id="2oI-Rn-ZJC"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Transformations" id="c8a-y6-VQd"> + <items> + <menuItem title="Make Upper Case" id="vmV-6d-7jI"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/> + </connections> + </menuItem> + <menuItem title="Make Lower Case" id="d9M-CD-aMd"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/> + </connections> + </menuItem> + <menuItem title="Capitalize" id="UEZ-Bs-lqG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Speech" id="xrE-MZ-jX0"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Speech" id="3rS-ZA-NoH"> + <items> + <menuItem title="Start Speaking" id="Ynk-f8-cLZ"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/> + </connections> + </menuItem> + <menuItem title="Stop Speaking" id="Oyz-dy-DGm"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Format" id="jxT-CU-nIS"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Format" id="GEO-Iw-cKr"> + <items> + <menuItem title="Font" id="Gi5-1S-RQB"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq"> + <items> + <menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq"> + <connections> + <action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/> + </connections> + </menuItem> + <menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27"> + <connections> + <action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/> + </connections> + </menuItem> + <menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq"> + <connections> + <action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/> + </connections> + </menuItem> + <menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S"> + <connections> + <action selector="underline:" target="-1" id="FYS-2b-JAY"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/> + <menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL"> + <connections> + <action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/> + </connections> + </menuItem> + <menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST"> + <connections> + <action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/> + <menuItem title="Kern" id="jBQ-r6-VK2"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Kern" id="tlD-Oa-oAM"> + <items> + <menuItem title="Use Default" id="GUa-eO-cwY"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/> + </connections> + </menuItem> + <menuItem title="Use None" id="cDB-IK-hbR"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/> + </connections> + </menuItem> + <menuItem title="Tighten" id="46P-cB-AYj"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/> + </connections> + </menuItem> + <menuItem title="Loosen" id="ogc-rX-tC1"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Ligatures" id="o6e-r0-MWq"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Ligatures" id="w0m-vy-SC9"> + <items> + <menuItem title="Use Default" id="agt-UL-0e3"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/> + </connections> + </menuItem> + <menuItem title="Use None" id="J7y-lM-qPV"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/> + </connections> + </menuItem> + <menuItem title="Use All" id="xQD-1f-W4t"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Baseline" id="OaQ-X3-Vso"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Baseline" id="ijk-EB-dga"> + <items> + <menuItem title="Use Default" id="3Om-Ey-2VK"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="unscript:" target="-1" id="0vZ-95-Ywn"/> + </connections> + </menuItem> + <menuItem title="Superscript" id="Rqc-34-cIF"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="superscript:" target="-1" id="3qV-fo-wpU"/> + </connections> + </menuItem> + <menuItem title="Subscript" id="I0S-gh-46l"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="subscript:" target="-1" id="Q6W-4W-IGz"/> + </connections> + </menuItem> + <menuItem title="Raise" id="2h7-ER-AoG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/> + </connections> + </menuItem> + <menuItem title="Lower" id="1tx-W0-xDw"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/> + <menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk"> + <connections> + <action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/> + <menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="copyFont:" target="-1" id="GJO-xA-L4q"/> + </connections> + </menuItem> + <menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="pasteFont:" target="-1" id="JfD-CL-leO"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Text" id="Fal-I4-PZk"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Text" id="d9c-me-L2H"> + <items> + <menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1"> + <connections> + <action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/> + </connections> + </menuItem> + <menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb"> + <connections> + <action selector="alignCenter:" target="-1" id="spX-mk-kcS"/> + </connections> + </menuItem> + <menuItem title="Justify" id="J5U-5w-g23"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="alignJustified:" target="-1" id="ljL-7U-jND"/> + </connections> + </menuItem> + <menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4"> + <connections> + <action selector="alignRight:" target="-1" id="r48-bG-YeY"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/> + <menuItem title="Writing Direction" id="H1b-Si-o9J"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd"> + <items> + <menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem id="YGs-j5-SAR"> + <string key="title"> Default</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/> + </connections> + </menuItem> + <menuItem id="Lbh-J2-qVU"> + <string key="title"> Left to Right</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/> + </connections> + </menuItem> + <menuItem id="jFq-tB-4Kx"> + <string key="title"> Right to Left</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="swp-gr-a21"/> + <menuItem title="Selection" enabled="NO" id="cqv-fj-IhA"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem id="Nop-cj-93Q"> + <string key="title"> Default</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/> + </connections> + </menuItem> + <menuItem id="BgM-ve-c93"> + <string key="title"> Left to Right</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/> + </connections> + </menuItem> + <menuItem id="RB4-Sm-HuC"> + <string key="title"> Right to Left</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/> + <menuItem title="Show Ruler" id="vLm-3I-IUL"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/> + </connections> + </menuItem> + <menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5"> + <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> + <connections> + <action selector="copyRuler:" target="-1" id="71i-fW-3W2"/> + </connections> + </menuItem> + <menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI"> + <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> + <connections> + <action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="View" id="H8h-7b-M4v"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="View" id="HyV-fh-RgO"> + <items> + <menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/> + </connections> + </menuItem> + <menuItem title="Customize Toolbar…" id="1UK-8n-QPP"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Window" id="aUF-d1-5bR"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo"> + <items> + <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV"> + <connections> + <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/> + </connections> + </menuItem> + <menuItem title="Zoom" id="R4o-n2-Eq4"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/> + <menuItem title="Bring All to Front" id="LE2-aR-0XJ"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Help" id="wpr-3q-Mcd"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ"> + <items> + <menuItem title="CocoaApp Help" keyEquivalent="?" id="FKE-Sm-Kum"> + <connections> + <action selector="showHelp:" target="-1" id="y7X-2Q-9no"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + <window title="CocoaApp" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g"> + <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> + <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> + <rect key="contentRect" x="335" y="390" width="480" height="360"/> + <rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/> + <view key="contentView" id="EiT-Mj-1SZ"> + <rect key="frame" x="0.0" y="0.0" width="480" height="360"/> + <autoresizingMask key="autoresizingMask"/> + </view> + </window> + </objects> +</document> diff --git a/examples/install-bundle/Storyboard.storyboard b/examples/install-bundle/Storyboard.storyboard new file mode 100644 index 000000000..41510ae29 --- /dev/null +++ b/examples/install-bundle/Storyboard.storyboard @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="8152.3" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> + <dependencies> + <deployment version="0.0" identifier="macosx"/> + <development version="5100" identifier="xcode"/> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8152.3"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="hyC-et-BQD"> + <objects> + <viewController storyboardIdentifier="Main" id="1os-k8-h10" sceneMemberID="viewController"> + <view key="view" id="qKA-a5-eUe"> + <rect key="frame" x="0.0" y="0.0" width="450" height="300"/> + <autoresizingMask key="autoresizingMask"/> + </view> + <connections> + <segue destination="Yem-rc-72E" kind="show" id="smB-wf-uRu"/> + <segue destination="Iqk-Fi-Vhk" kind="show" id="mam-9U-Q1A"/> + </connections> + </viewController> + <customObject id="2Oa-eW-Ce9" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="479" y="205"/> + </scene> + <!--View Controller--> + <scene sceneID="ivR-Sv-tI6"> + <objects> + <viewController id="Iqk-Fi-Vhk" sceneMemberID="viewController"> + <view key="view" id="HRv-3O-Qxh"> + <rect key="frame" x="0.0" y="0.0" width="450" height="300"/> + <autoresizingMask key="autoresizingMask"/> + </view> + </viewController> + <customObject id="Lyt-Nt-lfk" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="946" y="206"/> + </scene> + <!--View Controller--> + <scene sceneID="YQV-Q9-5te"> + <objects> + <viewController id="Yem-rc-72E" sceneMemberID="viewController"> + <view key="view" id="ODp-aO-Dmf"> + <rect key="frame" x="0.0" y="0.0" width="450" height="300"/> + <autoresizingMask key="autoresizingMask"/> + </view> + </viewController> + <customObject id="W89-TH-tp2" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="728" y="553"/> + </scene> + </scenes> +</document> diff --git a/examples/install-bundle/assetcatalog1.xcassets/other.imageset/Contents.json b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/Contents.json new file mode 100644 index 000000000..4b1cfb1f0 --- /dev/null +++ b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "icon_16x16.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "icon_16x16@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +}
\ No newline at end of file diff --git a/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16.png b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..60365798f --- /dev/null +++ b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16.png diff --git a/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.png b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..20369000d --- /dev/null +++ b/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.png diff --git a/examples/install-bundle/assetcatalog2.xcassets/other.imageset/Contents.json b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/Contents.json new file mode 100644 index 000000000..4b1cfb1f0 --- /dev/null +++ b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "icon_16x16.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "icon_16x16@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +}
\ No newline at end of file diff --git a/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16.png b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..60365798f --- /dev/null +++ b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16.png diff --git a/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.png b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..20369000d --- /dev/null +++ b/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.png diff --git a/examples/install-bundle/install-bundle.qbs b/examples/install-bundle/install-bundle.qbs index a1b58e3e3..5659f3c72 100644 --- a/examples/install-bundle/install-bundle.qbs +++ b/examples/install-bundle/install-bundle.qbs @@ -4,31 +4,25 @@ import qbs.FileInfo Project { CppApplication { Depends { name: "coreutils" } + Depends { name: "ib"; condition: qbs.targetOS.contains("darwin") } Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } name: "window" targetName: bundle.isBundle ? "Window" : "window" - files: ["main.cpp"] - - property bool install: true - property string installDir: bundle.isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") - - Group { - fileTagsFilter: ["application"] - qbs.install: install - qbs.installDir: bundle.isBundle ? FileInfo.joinPaths(installDir, FileInfo.path(bundle.executablePath)) : installDir - } + files: [ + "main.cpp", + "assetcatalog1.xcassets", + "assetcatalog2.xcassets", + "white.iconset", + "MainMenu.xib", + "Storyboard.storyboard" + ] Group { - fileTagsFilter: ["aggregate_infoplist"] - qbs.install: install && bundle.isBundle && !bundle.embedInfoPlist - qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.infoPlistPath)) - } - - Group { - fileTagsFilter: ["pkginfo"] - qbs.install: install && bundle.isBundle - qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.pkgInfoPath)) + fileTagsFilter: bundle.isBundle ? ["bundle.content"] : ["application"] + qbs.install: true + qbs.installDir: bundle.isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") + qbs.installSourceBase: product.buildDirectory } } @@ -39,19 +33,11 @@ Project { targetName: bundle.isBundle ? "CoreUtils" : "coreutils" files: ["coreutils.cpp", "coreutils.h"] - property bool install: true - property string installDir: bundle.isBundle ? "Library/Frameworks" : (qbs.targetOS.contains("windows") ? "" : "lib") - - Group { - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_import"] - qbs.install: install - qbs.installDir: bundle.isBundle ? FileInfo.joinPaths(installDir, FileInfo.path(bundle.executablePath)) : installDir - } - Group { - fileTagsFilter: ["aggregate_infoplist"] - qbs.install: install && bundle.isBundle && !bundle.embedInfoPlist - qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.infoPlistPath)) + fileTagsFilter: bundle.isBundle ? ["bundle.content"] : ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_import"] + qbs.install: true + qbs.installDir: bundle.isBundle ? "Library/Frameworks" : (qbs.targetOS.contains("windows") ? "" : "lib") + qbs.installSourceBase: product.buildDirectory } } } diff --git a/examples/install-bundle/white.iconset/icon_16x16.png b/examples/install-bundle/white.iconset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..60365798f --- /dev/null +++ b/examples/install-bundle/white.iconset/icon_16x16.png diff --git a/examples/install-bundle/white.iconset/icon_16x16@2x.png b/examples/install-bundle/white.iconset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..20369000d --- /dev/null +++ b/examples/install-bundle/white.iconset/icon_16x16@2x.png diff --git a/share/qbs/imports/qbs/PathTools/path-tools.js b/share/qbs/imports/qbs/PathTools/path-tools.js index bf42a390b..ad04c5db9 100644 --- a/share/qbs/imports/qbs/PathTools/path-tools.js +++ b/share/qbs/imports/qbs/PathTools/path-tools.js @@ -30,46 +30,45 @@ var FileInfo = loadExtension("qbs.FileInfo"); -function applicationFileName(product) { +function _bundleExecutableTemporaryFilePath(product) { + return ".tmp/" + FileInfo.fileName(bundleExecutableFilePath(product)); +} + +function bundleExecutableFilePath(product) { + return product.moduleProperty("bundle", "executablePath"); +} + +function applicationFilePath(product) { + if (product.moduleProperty("bundle", "isBundle")) + return _bundleExecutableTemporaryFilePath(product); + return product.moduleProperty("cpp", "executablePrefix") + product.targetName + product.moduleProperty("cpp", "executableSuffix"); } -function applicationFilePath(product) { +function loadableModuleFilePath(product) { if (product.moduleProperty("bundle", "isBundle")) - return product.moduleProperty("bundle", "executablePath"); - else - return applicationFileName(product); -} + return _bundleExecutableTemporaryFilePath(product); -function loadableModuleFileName(product) { return product.moduleProperty("cpp", "loadableModulePrefix") + product.targetName + product.moduleProperty("cpp", "loadableModuleSuffix"); } -function loadableModuleFilePath(product) { +function staticLibraryFilePath(product) { if (product.moduleProperty("bundle", "isBundle")) - return product.moduleProperty("bundle", "executablePath"); - else - return loadableModuleFileName(product); -} + return _bundleExecutableTemporaryFilePath(product); -function staticLibraryFileName(product) { return product.moduleProperty("cpp", "staticLibraryPrefix") + product.targetName + product.moduleProperty("cpp", "staticLibrarySuffix"); } -function staticLibraryFilePath(product) { +function dynamicLibraryFilePath(product, version, maxParts) { if (product.moduleProperty("bundle", "isBundle")) - return product.moduleProperty("bundle", "executablePath"); - else - return staticLibraryFileName(product); -} + return _bundleExecutableTemporaryFilePath(product); -function dynamicLibraryFileName(product, version, maxParts) { // If no override version was given, use the product's version // We specifically want to differentiate between undefined and i.e. // empty string as empty string should be taken to mean "no version" @@ -104,13 +103,6 @@ function dynamicLibraryFileName(product, version, maxParts) { return fileName; } -function dynamicLibraryFilePath(product, version, maxParts) { - if (product.moduleProperty("bundle", "isBundle")) - return product.moduleProperty("bundle", "executablePath"); - else - return dynamicLibraryFileName(product, version, maxParts); -} - function importLibraryFilePath(product) { return product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName @@ -132,18 +124,19 @@ function debugInfoFileName(product) { || !debugInfoIsBundle(product)) suffix = product.moduleProperty("cpp", "debugInfoSuffix"); - if (!product.moduleProperty("bundle", "isBundle")) { + if (product.moduleProperty("bundle", "isBundle")) { + return FileInfo.fileName(bundleExecutableFilePath(product)) + suffix; + } else { if (product.type.contains("application")) - return applicationFileName(product) + suffix; + return applicationFilePath(product) + suffix; else if (product.type.contains("dynamiclibrary")) - return dynamicLibraryFileName(product) + suffix; + return dynamicLibraryFilePath(product) + suffix; else if (product.type.contains("loadablemodule")) - return loadableModuleFileName(product) + suffix; + return loadableModuleFilePath(product) + suffix; else if (product.type.contains("staticlibrary")) - return staticLibraryFileName(product) + suffix; + return staticLibraryFilePath(product) + suffix; + return product.targetName + suffix; } - - return product.targetName + suffix; } function debugInfoBundlePath(product) { diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs index 7c2278977..0bf25033d 100644 --- a/share/qbs/modules/bundle/BundleModule.qbs +++ b/share/qbs/modules/bundle/BundleModule.qbs @@ -94,7 +94,7 @@ Module { } } - additionalProductTypes: ["bundle"] + additionalProductTypes: ["bundle.content"] property bool isBundle: !product.consoleApplication && qbs.targetOS.contains("darwin") && product.type.containsAny(["application", "dynamiclibrary", "loadablemodule"]) @@ -265,17 +265,20 @@ Module { multiplex: true inputs: ["qbs", "infoplist", "partial_infoplist"] - outputFileTags: ["aggregate_infoplist"] + outputFileTags: ["bundle.input", "aggregate_infoplist"] outputArtifacts: { var artifacts = []; var embed = ModUtils.moduleProperty(product, "embedInfoPlist"); if (ModUtils.moduleProperty(product, "isBundle") || embed) { artifacts.push({ filePath: FileInfo.joinPaths( - product.destinationDirectory, embed - ? product.name + "-Info.plist" - : ModUtils.moduleProperty(product, "infoPlistPath")), - fileTags: ["aggregate_infoplist"] + product.destinationDirectory, product.name + "-Info.plist"), + fileTags: ["aggregate_infoplist"].concat(!embed ? ["bundle.input"] : []), + bundle: { + _bundleFilePath: FileInfo.joinPaths( + product.destinationDirectory, + ModUtils.moduleProperty(product, "infoPlistPath")), + } }); } return artifacts; @@ -448,13 +451,14 @@ Module { multiplex: true inputs: ["aggregate_infoplist"] - outputFileTags: ["pkginfo"] + outputFileTags: ["bundle.input", "pkginfo"] outputArtifacts: { var artifacts = []; if (ModUtils.moduleProperty(product, "isBundle") && ModUtils.moduleProperty(product, "generatePackageInfo")) { artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")), - fileTags: ["pkginfo"] + filePath: FileInfo.joinPaths(product.destinationDirectory, "PkgInfo"), + fileTags: ["bundle.input", "pkginfo"], + bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")) } }); } return artifacts; @@ -486,12 +490,14 @@ Module { Rule { condition: qbs.targetOS.contains("darwin") multiplex: true - inputs: ["aggregate_infoplist", "pkginfo", "hpp", + inputs: ["bundle.input", + "aggregate_infoplist", "pkginfo", "hpp", "icns", "xcent", "compiled_ibdoc", "compiled_assetcatalog", "xcode.provisioningprofile.main"] - outputFileTags: ["bundle", + outputFileTags: [ + "bundle.content", "bundle.symlink.headers", "bundle.symlink.private-headers", "bundle.symlink.resources", "bundle.symlink.executable", "bundle.symlink.version", "bundle.hpp", "bundle.resource", @@ -499,10 +505,15 @@ Module { outputArtifacts: { var i, artifacts = []; if (ModUtils.moduleProperty(product, "isBundle")) { - artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName")), - fileTags: ["bundle"] - }); + for (i in inputs["bundle.input"]) { + var fp = inputs["bundle.input"][i].moduleProperty("bundle", "_bundleFilePath"); + if (!fp) + throw("Artifact " + inputs["bundle.input"][i].filePath + " has no associated bundle file path"); + artifacts.push({ + filePath: fp, + fileTags: ["bundle.content", "bundle.content.copied"] + }); + } for (i in inputs["xcode.provisioningprofile.main"]) { var ext = inputs["xcode.provisioningprofile.main"][i].fileName.split('.')[1]; @@ -511,7 +522,7 @@ Module { ModUtils.moduleProperty(product, "contentsFolderPath"), "embedded." + ext), - fileTags: ["bundle.provisioningprofile"] + fileTags: ["bundle.provisioningprofile", "bundle.content"] }); } @@ -522,7 +533,7 @@ Module { if (publicHeaders && publicHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Headers"), - fileTags: ["bundle.symlink.headers"] + fileTags: ["bundle.symlink.headers", "bundle.content"] }); } @@ -530,23 +541,23 @@ Module { if (privateHeaders && privateHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "PrivateHeaders"), - fileTags: ["bundle.symlink.private-headers"] + fileTags: ["bundle.symlink.private-headers", "bundle.content"] }); } artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Resources"), - fileTags: ["bundle.symlink.resources"] + fileTags: ["bundle.symlink.resources", "bundle.content"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), product.targetName), - fileTags: ["bundle.symlink.executable"] + fileTags: ["bundle.symlink.executable", "bundle.content"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "versionsFolderPath"), "Current"), - fileTags: ["bundle.symlink.version"] + fileTags: ["bundle.symlink.version", "bundle.content"] }); } @@ -557,7 +568,7 @@ Module { for (i in sources) { artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), - fileTags: ["bundle.hpp"] + fileTags: ["bundle.hpp", "bundle.content"] }); } } @@ -567,9 +578,15 @@ Module { destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), - fileTags: ["bundle.resource"] + fileTags: ["bundle.resource", "bundle.content"] }); } + + var wrapperPath = FileInfo.joinPaths( + product.destinationDirectory, + ModUtils.moduleProperty(product, "bundleName")); + for (var i = 0; i < artifacts.length; ++i) + artifacts[i].bundle = { wrapperPath: wrapperPath }; } return artifacts; } @@ -643,6 +660,30 @@ Module { commands.push(cmd); } + function sortedArtifactList(list, func) { + if (list) { + return list.sort(func || (function (a, b) { + return a.filePath.localeCompare(b.filePath); + })); + } + } + + var bundleInputs = sortedArtifactList(inputs["bundle.input"], function (a, b) { + return a.moduleProperty("bundle", "_bundleFilePath").localeCompare( + b.moduleProperty("bundle", "_bundleFilePath")); + }); + var bundleContents = sortedArtifactList(outputs["bundle.content.copied"]); + for (i in bundleContents) { + cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.source = bundleInputs[i].filePath; + cmd.destination = bundleContents[i].filePath; + cmd.sourceCode = function() { + File.copy(source, destination); + }; + commands.push(cmd); + } + var provisioningProfiles = outputs["bundle.provisioningprofile"]; for (i in provisioningProfiles) { cmd = new JavaScriptCommand(); diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 3f5aa706d..5e88e59c7 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -285,13 +285,20 @@ CppModule { inputsFromDependencies: ["dynamiclibrary_copy", "staticlibrary"] outputFileTags: [ + "bundle.input", "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_copy", "debuginfo_dll" ] outputArtifacts: { + if (product.type.contains("bundle") && !product.type.contains("dynamiclibrary")) + return []; var lib = { filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product), - fileTags: ["dynamiclibrary"] + fileTags: ["bundle.input", "dynamiclibrary"], + bundle: { + _bundleFilePath: product.destinationDirectory + "/" + + PathTools.bundleExecutableFilePath(product) + } }; var libCopy = { // List of libfoo's public symbols for smart re-linking. @@ -307,7 +314,7 @@ CppModule { for (var i = 0; i < maxVersionParts; ++i) { var symlink = { filePath: product.destinationDirectory + "/" - + PathTools.dynamicLibraryFileName(product, undefined, i), + + PathTools.dynamicLibraryFilePath(product, undefined, i), fileTags: ["dynamiclibrary_symlink"] }; if (i > 0 && artifacts[i-1].filePath == symlink.filePath) @@ -329,9 +336,11 @@ CppModule { inputs: ["obj", "linkerscript"] inputsFromDependencies: ["dynamiclibrary", "staticlibrary"] - outputFileTags: ["staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] + outputFileTags: ["bundle.input", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] outputArtifacts: { - var tags = ["staticlibrary"]; + if (product.type.contains("bundle") && !product.type.contains("staticlibrary")) + return []; + var tags = ["bundle.input", "staticlibrary"]; for (var i = 0; i < inputs["obj"].length; ++i) { var ft = inputs["obj"][i].fileTags; if (ft.contains("c_obj")) @@ -364,7 +373,11 @@ CppModule { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)), fileTags: tags, - cpp: { "staticLibraries": staticLibraries, "dynamicLibraries": dynamicLibraries } + cpp: { "staticLibraries": staticLibraries, "dynamicLibraries": dynamicLibraries }, + bundle: { + _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, + PathTools.bundleExecutableFilePath(product)) + } }]; } @@ -393,12 +406,18 @@ CppModule { } inputsFromDependencies: ["dynamiclibrary_copy", "staticlibrary"] - outputFileTags: ["loadablemodule", "debuginfo_loadablemodule"] + outputFileTags: ["bundle.input", "loadablemodule", "debuginfo_loadablemodule"] outputArtifacts: { + if (product.type.contains("bundle") && !product.type.contains("loadablemodule")) + return []; var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.loadableModuleFilePath(product)), - fileTags: ["loadablemodule"] + fileTags: ["bundle.input", "loadablemodule"], + bundle: { + _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, + PathTools.bundleExecutableFilePath(product)) + } } return [app].concat(Gcc.debugInfoArtifacts(product, "loadablemodule")); } @@ -421,12 +440,18 @@ CppModule { } inputsFromDependencies: ["dynamiclibrary_copy", "staticlibrary"] - outputFileTags: ["application", "debuginfo_app"] + outputFileTags: ["bundle.input", "application", "debuginfo_app"] outputArtifacts: { + if (product.type.contains("bundle") && !product.type.contains("application")) + return []; var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.applicationFilePath(product)), - fileTags: ["application"] + fileTags: ["bundle.input", "application"], + bundle: { + _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, + PathTools.bundleExecutableFilePath(product)) + } } return [app].concat(Gcc.debugInfoArtifacts(product, "app")); } diff --git a/share/qbs/modules/cpp/ios-gcc.qbs b/share/qbs/modules/cpp/ios-gcc.qbs index 2ff4dc49c..817eee4fa 100644 --- a/share/qbs/modules/cpp/ios-gcc.qbs +++ b/share/qbs/modules/cpp/ios-gcc.qbs @@ -62,7 +62,7 @@ DarwinGCC { Rule { condition: !product.moduleProperty("qbs", "targetOS").contains("ios-simulator") - inputsFromDependencies: ["bundle"] + inputsFromDependencies: ["bundle.content"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".ipa") diff --git a/share/qbs/modules/ib/IBModule.qbs b/share/qbs/modules/ib/IBModule.qbs index f0206dd4c..af0e166f7 100644 --- a/share/qbs/modules/ib/IBModule.qbs +++ b/share/qbs/modules/ib/IBModule.qbs @@ -129,12 +129,17 @@ Module { Rule { inputs: ["iconset"] - Artifact { - filePath: FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), - input.completeBaseName + - ModUtils.moduleProperty(product, "appleIconSuffix")) - fileTags: ["icns"] - } + outputFileTags: ["icns", "bundle.input"] + outputArtifacts: ([{ + filePath: FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + + ModUtils.moduleProperty(product, "appleIconSuffix")), + fileTags: ["icns", "bundle.input"], + bundle: { + _bundleFilePath: FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), + input.completeBaseName + + ModUtils.moduleProperty(product, "appleIconSuffix")) + } + }]) prepare: { var args = ["--convert", "icns", "--output", output.filePath, input.filePath]; @@ -158,7 +163,7 @@ Module { prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "ibtoolPath"), - Ib.ibtooldArguments(product, inputs, outputs)); + Ib.ibtooldArguments(product, inputs, input, outputs)); cmd.description = "compiling " + input.fileName; // Also display the language name of the nib/storyboard being compiled if it has one @@ -186,11 +191,14 @@ Module { multiplex: true outputArtifacts: Ib.actoolOutputArtifacts(product, inputs) - outputFileTags: ["compiled_assetcatalog", "partial_infoplist"] + outputFileTags: ["bundle.input", "compiled_assetcatalog", "partial_infoplist"] prepare: { + var mkdir = new Command("mkdir", ["-p", product.buildDirectory + "/actool.dir"]); + mkdir.silent = true; + var cmd = new Command(ModUtils.moduleProperty(product, "actoolPath"), - Ib.ibtooldArguments(product, inputs, outputs)); + Ib.ibtooldArguments(product, inputs, input, outputs)); cmd.description = inputs["assetcatalog"].map(function (input) { return "compiling " + input.fileName; }).join('\n'); @@ -200,7 +208,7 @@ Module { return ""; }; - return cmd; + return [mkdir, cmd]; } } } diff --git a/share/qbs/modules/ib/ib.js b/share/qbs/modules/ib/ib.js index b38fcd806..fb18e5d40 100644 --- a/share/qbs/modules/ib/ib.js +++ b/share/qbs/modules/ib/ib.js @@ -44,7 +44,7 @@ function artifactsFromInputs(inputs) { return artifacts; } -function ibtooldArguments(product, inputs, outputs, overrideOutput) { +function ibtooldArguments(product, inputs, input, outputs, overrideOutput) { var i; var args = []; var allInputs = artifactsFromInputs(inputs); @@ -125,12 +125,11 @@ function ibtooldArguments(product, inputs, outputs, overrideOutput) { if (overrideOutput) { args.push("--compile", overrideOutput); } else { - if (outputs.compiled_ibdoc_main) - args.push("--compile", outputs.compiled_ibdoc_main[0].filePath); - if (outputs.compiled_assetcatalog) - args.push("--compile", - BundleTools.destinationDirectoryForResource(product, inputs.assetcatalog[0])); + args.push("--compile", product.buildDirectory + "/actool.dir"); + else // compiled_ibdoc + args.push("--compile", product.buildDirectory + "/ibtool.dir/" + + ibtoolCompiledDirSuffix(product, input)); } for (i in allInputs) @@ -149,21 +148,25 @@ function ibtoolFileTaggers(fileTags) { if (!ext) throw "unknown ibtool input file tags: " + fileTags; - var t = "compiled_ibdoc"; + var t = ["bundle.input", "compiled_ibdoc"]; return { - ".nib": [t, "compiled_" + ext + (ext !== "nib" ? "_nib" : "")], - ".plist": [t, "compiled_" + ext + "_infoplist"], - ".storyboard": [t, "compiled_" + ext] + ".nib": t.concat(["compiled_" + ext + (ext !== "nib" ? "_nib" : "")]), + ".plist": t.concat(["compiled_" + ext + "_infoplist"]), + ".storyboard": t.concat(["compiled_" + ext]) }; } -function ibtoolOutputArtifacts(product, inputs, input) { +function ibtoolCompiledDirSuffix(product, input) { var suffix = input.completeBaseName; if (input.fileTags.contains("nib")) suffix += ModUtils.moduleProperty(product, "compiledNibSuffix"); else if (input.fileTags.contains("storyboard")) suffix += ModUtils.moduleProperty(product, "compiledStoryboardSuffix"); + return suffix; +} +function ibtoolOutputArtifacts(product, inputs, input) { + var suffix = ibtoolCompiledDirSuffix(product, input); var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); @@ -173,13 +176,15 @@ function ibtoolOutputArtifacts(product, inputs, input) { // Last --output-format argument overrides any previous ones // Append the name of the base output since it can be either a file or a directory // in the case of XIB compilations - return ibtooldArguments(product, inputs, + return ibtooldArguments(product, inputs, input, undefined, FileInfo.joinPaths(outputDirectory, suffix)) .concat(["--output-format", "xml1"]); }; - var artifacts = tracker.artifacts( - FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input))); + var ibtoolBuildDirectory = product.buildDirectory + "/ibtool.dir"; + var main = BundleTools.destinationDirectoryForResource(product, input); + + var artifacts = tracker.artifacts(ibtoolBuildDirectory); if (product.moduleProperty("ib", "ibtoolVersionMajor") >= 6) { var prefix = input.fileTags.contains("storyboard") ? "SB" : ""; @@ -188,28 +193,13 @@ function ibtoolOutputArtifacts(product, inputs, input) { artifacts.push({ filePath: path, fileTags: ["partial_infoplist"] }); } - // Tag the "main" output + // Let the output artifacts known the "main" output // This can be either a file or directory so the artifact might already exist in the output list - var main = FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), - suffix); - var mainTags = ["compiled_ibdoc", "compiled_ibdoc_main"]; - var mainIndex = -1; for (var i = 0; i < artifacts.length; ++i) { - if (artifacts[i].filePath === main) { - mainIndex = i; - break; - } - } - - if (mainIndex === -1) { - // artifact not in list - the output was a directory (unflatted nib or storyboard) - artifacts.splice(0, 0, { - filePath: main, - fileTags: mainTags - }); - } else { - // artifact in list - the output was a file (flattened nib) - artifacts[mainIndex].fileTags = mainTags.uniqueConcat(artifacts[mainIndex].fileTags); + if (artifacts[i].fileTags.contains("compiled_ibdoc")) + artifacts[i].bundle = { + _bundleFilePath: artifacts[i].filePath.replace(ibtoolBuildDirectory, main) + }; } return artifacts; @@ -224,12 +214,11 @@ function actoolOutputArtifacts(product, inputs) { tracker.command = ModUtils.moduleProperty(product, "actoolPath"); tracker.commandArgsFunction = function (outputDirectory) { // Last --output-format argument overrides any previous ones - return ibtooldArguments(product, inputs, + return ibtooldArguments(product, inputs, undefined, undefined, outputDirectory).concat(["--output-format", "xml1"]); }; tracker.processStdOutFunction = parseActoolOutput; - var artifacts = tracker.artifacts(BundleTools.destinationDirectoryForResource(product, - inputs.assetcatalog[0])); + var artifacts = tracker.artifacts(product.buildDirectory + "/actool.dir"); // Newer versions of actool don't generate *anything* if there's no input; // in that case a partial Info.plist would not have been generated either @@ -241,6 +230,16 @@ function actoolOutputArtifacts(product, inputs) { }); } + for (var i = 0; i < artifacts.length; ++i) { + if (artifacts[i].fileTags.contains("compiled_assetcatalog")) { + artifacts[i].bundle = { + _bundleFilePath: artifacts[i].filePath.replace( + product.buildDirectory + "/actool.dir", + BundleTools.destinationDirectoryForResource(product, inputs.assetcatalog[0])) + }; + } + } + return artifacts; } @@ -260,7 +259,7 @@ function parseActoolOutput(output) { continue; var tags = files[i].endsWith(".plist") ? ["partial_infoplist"] - : ["compiled_assetcatalog"]; + : ["bundle.input", "compiled_assetcatalog"]; artifacts.push({ filePath: files[i], fileTags: tags diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs index 652ee2053..98b7bd9dd 100644 --- a/share/qbs/modules/xcode/xcode.qbs +++ b/share/qbs/modules/xcode/xcode.qbs @@ -329,7 +329,7 @@ Module { Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".xcent") - fileTags: ["xcent"] + fileTags: ["xcent", "bundle.input"] } prepare: { diff --git a/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs b/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs index 5b372589a..a7c3e20bf 100644 --- a/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs +++ b/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs @@ -1,14 +1,7 @@ import qbs Project { - property stringList bundleFileTags: [ - "aggregate_infoplist", "pkginfo", "hpp", - "icns", "xcent", - "compiled_ibdoc", "compiled_assetcatalog", - "bundle.symlink.headers", "bundle.symlink.private-headers", - "bundle.symlink.resources", "bundle.symlink.executable", - "bundle.symlink.version", "bundle.hpp", "bundle.resource", - ] + property stringList bundleFileTags: ["bundle.content"] property stringList buildableProducts: ["A", "B", "C", "D", "E", "F", "G"] |