diff options
author | Jake Petroules <jake.petroules@qt.io> | 2017-01-26 19:28:38 -0800 |
---|---|---|
committer | Jake Petroules <jake.petroules@qt.io> | 2017-02-08 11:16:22 +0000 |
commit | e9fb1cc49edc9d50be5cff2f08599a9056627581 (patch) | |
tree | 5778e6e1715242d36315df6878fccd262764ee94 | |
parent | 08c5bfa1a860cf33ed4da951a543d434045e8345 (diff) | |
download | qbs-e9fb1cc49edc9d50be5cff2f08599a9056627581.tar.gz |
Attach the bundle.content file tag to files that are part of a bundle
This simplifies installation for end users, as they only ever have to
use this one tag to install an entire bundle, rather than having to
remember every possible file tag attached to the output artifacts of
rules which install their output to a bundle.
Refactor associated rules to handle this new internal workflow. This
paves the way for other new functionality like bundle embedding.
Change-Id: I76369383ae08d1ff5433b73d517a657dbd329b78
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
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"] |