mirror of
https://github.com/ONLYOFFICE/build_tools.git
synced 2026-04-07 14:06:31 +08:00
Compare commits
561 Commits
fix/docs-g
...
v9.2.0.88
| Author | SHA1 | Date | |
|---|---|---|---|
| 73576ff817 | |||
| b4ba33bb69 | |||
| e04df1ba9a | |||
| dd148a105e | |||
| acf75749c2 | |||
| 354e4a6a04 | |||
| b85fb9c07c | |||
| 40b95455a0 | |||
| 62ab1f9935 | |||
| dd26863a2b | |||
| c02a387a64 | |||
| 0fd6852fe8 | |||
| 0dbf009c6b | |||
| 44b6d2d64f | |||
| b2ce2bbcad | |||
| 133192df35 | |||
| c45cf77747 | |||
| 9f898d6873 | |||
| 61bf2d9413 | |||
| 0c8b3e5919 | |||
| 6fd500e55d | |||
| 10f7dcee17 | |||
| 2fcdef2e00 | |||
| 2ec27065f8 | |||
| 4f804ba0e6 | |||
| 7fb05a51f9 | |||
| 30e3202fd5 | |||
| b6b09d17f4 | |||
| 8a70f3d14a | |||
| aaa5096526 | |||
| 668aa88c6e | |||
| ec544ca9ab | |||
| 17ee00a04c | |||
| bc4daa9546 | |||
| 099003b250 | |||
| 4ca5e4bcb5 | |||
| ee4469885e | |||
| 1350955f67 | |||
| de36280085 | |||
| 0399ea1cb1 | |||
| 41ed9824ab | |||
| 842df5ffd0 | |||
| d0e3f36313 | |||
| 18605dc68f | |||
| 5004a30908 | |||
| 33e41ed704 | |||
| 1f4c88a489 | |||
| 283977f014 | |||
| e71e0bee74 | |||
| fe9847f246 | |||
| f79bfd099b | |||
| 3ec9b4dba5 | |||
| 0c7348fc89 | |||
| 97b615c36a | |||
| 59f95f52ce | |||
| ba04810793 | |||
| aea03d8554 | |||
| 09247281ef | |||
| 7b31d85c7c | |||
| 3ad5b9d05d | |||
| 894f23b292 | |||
| 125d0112e4 | |||
| b46d6075e4 | |||
| c535c411da | |||
| 599db1f8be | |||
| 10ff21a974 | |||
| c60dc81694 | |||
| 6de1859441 | |||
| 70a50da160 | |||
| 3ca2efeb30 | |||
| 496594e77f | |||
| 8ebc7dba86 | |||
| 7da1a18753 | |||
| c16242f25f | |||
| 2f43d90ab9 | |||
| 6f242eee81 | |||
| f19a406ad2 | |||
| cfe69c6bcd | |||
| dcbeec9562 | |||
| 954e3b1ee8 | |||
| d5666b1152 | |||
| c4fa19a1c8 | |||
| 7d9444a727 | |||
| 3646a2560a | |||
| 2f877e0a4c | |||
| 434d6cc33c | |||
| 31386ad676 | |||
| 0d917471a7 | |||
| 4d91ac47ec | |||
| 44e346210b | |||
| 2ffc1b9347 | |||
| 7a58da1af1 | |||
| f703663342 | |||
| af9db63711 | |||
| 7e9d9051aa | |||
| 73b41a5588 | |||
| 1ab43f0551 | |||
| 79c4fa5042 | |||
| 944caac250 | |||
| 7fe4ade155 | |||
| 3d51a5e648 | |||
| d6af99141d | |||
| 568e84275c | |||
| de5e5fe938 | |||
| 152b524197 | |||
| 142e6541c7 | |||
| 357db616f7 | |||
| 8fc50cc0f2 | |||
| 1feed69b71 | |||
| 6b03a77791 | |||
| 31b4e29e37 | |||
| 08d8a02166 | |||
| e69a5135da | |||
| e768f17744 | |||
| 4e9251e45b | |||
| 2ec2173cad | |||
| 72d6298bbc | |||
| a00302ad1d | |||
| 56c93f97af | |||
| a7432a6b4b | |||
| 75faf391b6 | |||
| 9cefa13362 | |||
| 8f9835a7bd | |||
| 41a4e81c5a | |||
| 83374aa635 | |||
| 4e6b45043a | |||
| 72124a2305 | |||
| b4b84dc462 | |||
| 6cd690d6b6 | |||
| b4f863f00f | |||
| 88d0c54040 | |||
| 46a18695fa | |||
| 05f2f636df | |||
| 506f558eed | |||
| 38cd4e6e77 | |||
| f86376fbc2 | |||
| 3943237a64 | |||
| 37d256acda | |||
| 9cad51e611 | |||
| 3571e02abf | |||
| 123af8265a | |||
| 4f55f8cc90 | |||
| 9a3642572c | |||
| b93773ec78 | |||
| d2eb9b20af | |||
| f2cb4e6a51 | |||
| 5cdb4dae39 | |||
| 9102284b80 | |||
| 1f009d0942 | |||
| 566367daa5 | |||
| c36a390292 | |||
| 4a947d2a3c | |||
| 9b104f358e | |||
| c8a72c53b8 | |||
| 6a3d29bd00 | |||
| 97c8a33e5d | |||
| 39ff7e7692 | |||
| 4f9040d73b | |||
| 9579394788 | |||
| ea8a7bf52e | |||
| a1af0a6804 | |||
| 65e6f05385 | |||
| 08145c0d79 | |||
| c1f60e27c8 | |||
| 5168e20918 | |||
| 0968ca2566 | |||
| e461da3a1e | |||
| c6176a95f4 | |||
| 224db5eb54 | |||
| a6c315302b | |||
| ae3bc78b29 | |||
| 4c48514402 | |||
| e4bc6492be | |||
| 23a526f3a1 | |||
| df87cafbdb | |||
| 595e2eaa86 | |||
| 9440fc3494 | |||
| 56e2042711 | |||
| 30167dbf76 | |||
| 5a403cb3ac | |||
| f22bda85e4 | |||
| 4f09833650 | |||
| d435dd496b | |||
| 252a5c306d | |||
| 9710a074f8 | |||
| e4b91f1b24 | |||
| 6b3f100e7e | |||
| 573612c1c5 | |||
| ba31642a46 | |||
| 00c37bc9dd | |||
| a8ab257faf | |||
| fc9d060a78 | |||
| a640943c60 | |||
| 6c700fe492 | |||
| afb9b8b61a | |||
| 38c49f70e5 | |||
| bdc40e1572 | |||
| 73bf068cb0 | |||
| 6a4d3bff53 | |||
| dc3ceb6ef8 | |||
| a0cc2123bf | |||
| c71e5c5bde | |||
| 1f84a604d2 | |||
| 648dc2119e | |||
| 4f746cb484 | |||
| 853c760cc4 | |||
| 972bcc8064 | |||
| 2b6557f0ec | |||
| 053c0c2fe9 | |||
| caf79933d8 | |||
| debe284664 | |||
| d4231e0efa | |||
| de99e3f62e | |||
| 16858aa7c2 | |||
| 8beb8b3c84 | |||
| 8cf076aff8 | |||
| 55ddce5904 | |||
| aa5d06a1ec | |||
| 031a1119d6 | |||
| 316c3cec26 | |||
| 584513fb15 | |||
| 9203d68ed8 | |||
| 41abb6b09c | |||
| 7bb5e65810 | |||
| 49ede6a10b | |||
| ac394d8de6 | |||
| abde837a74 | |||
| 834fab5fc7 | |||
| d357abcfc9 | |||
| 119b5f6d33 | |||
| 8a70714eeb | |||
| 90903009f4 | |||
| 6f256be099 | |||
| 5568b7da2e | |||
| 0f89ba4247 | |||
| 4cefdc38fb | |||
| d1481021a7 | |||
| d7eaef6503 | |||
| 0c7b8a2b1c | |||
| 9b5b3eb77c | |||
| 9e31770bfa | |||
| 4d6b9f9463 | |||
| d2c79bb78d | |||
| e0aa6184d6 | |||
| 9c80b95dbe | |||
| bfd3bb009f | |||
| 7ef302fac1 | |||
| fece05de0b | |||
| 71a2981ae8 | |||
| de1d437576 | |||
| 2e179644b3 | |||
| c4551af253 | |||
| 28ca6676a5 | |||
| 31f679a050 | |||
| 64c32043cc | |||
| ea52e70a6d | |||
| 1d721e3e3e | |||
| 3e3b0127a6 | |||
| dcc9f8e669 | |||
| 67c454b469 | |||
| 1cc0528b11 | |||
| c3dce4bc91 | |||
| 990382512b | |||
| b6985ce27e | |||
| 65e36cd01a | |||
| caaebde240 | |||
| 7c130faac2 | |||
| 7ff5d2f40d | |||
| a353e89871 | |||
| c9151cd09d | |||
| 03f99c526d | |||
| 34a54bf88f | |||
| b40c0a0d74 | |||
| 519ea3fb6c | |||
| e4cc090bfd | |||
| c6138b3902 | |||
| 8ec240dcee | |||
| fa589c9523 | |||
| 5f2d8be5dc | |||
| 829228d28c | |||
| a7c9f3a0ce | |||
| e676ebcffd | |||
| 6fe22b14c6 | |||
| d50b171b54 | |||
| 19fc33b7f5 | |||
| d6cbfcbfe3 | |||
| 23db442c82 | |||
| e40f8c9a7e | |||
| 4d4d1612ce | |||
| ded3dfa63c | |||
| 6a2db3d59e | |||
| 48c8a635a8 | |||
| 1ac83e0ffd | |||
| ef6ecbbebd | |||
| f51b841320 | |||
| 7c0099c57e | |||
| 8f49dce1ed | |||
| a9bad0d5b7 | |||
| 702a83c010 | |||
| 227ecbde99 | |||
| ee52dbe5c4 | |||
| 0f0e0a0e52 | |||
| d288d6326c | |||
| b87e305c06 | |||
| 8516b163b4 | |||
| 4460d6ed13 | |||
| ab3165fdaf | |||
| 1539c187e3 | |||
| 78df8eb494 | |||
| eebbd513d3 | |||
| 2ab7616132 | |||
| 3be471b472 | |||
| a151375339 | |||
| ed2ab2d80b | |||
| 35f99ac3a0 | |||
| 836a0401ed | |||
| b8024df7d3 | |||
| 74c02f9d50 | |||
| 25a1e16824 | |||
| 7ee66bbafd | |||
| 2b07d1aa4d | |||
| c6acd6cdcd | |||
| cee122afa5 | |||
| 4c76406f8c | |||
| 6fd89057ec | |||
| ae8b77628e | |||
| 959d919d9e | |||
| bf7df0b45a | |||
| 3589ea0f60 | |||
| ad23ee2803 | |||
| bc59f739f5 | |||
| b8e42184f8 | |||
| 50c312513c | |||
| 427ae97dd2 | |||
| d80f1f1b0f | |||
| 520d779f04 | |||
| c4b938b7db | |||
| 9435cdc99b | |||
| cf90a5ce21 | |||
| 3f4d0cefa8 | |||
| 12ce537781 | |||
| 12d824fe2d | |||
| 8dcf0277ac | |||
| 6664051127 | |||
| 019f10ee86 | |||
| a7ee5d5679 | |||
| 7c31890fc0 | |||
| ad9258710b | |||
| 626dd37312 | |||
| b4d95ccbb9 | |||
| 0d0ae2b5e6 | |||
| d7b3b7f120 | |||
| 7a864171b3 | |||
| 8cfb8f3d84 | |||
| 2f39454d31 | |||
| de33755900 | |||
| d3d1080c89 | |||
| 539597f07c | |||
| 6e87116634 | |||
| 029b16ca68 | |||
| 40b11e192d | |||
| 72cc19f346 | |||
| efb22f741f | |||
| 2458673d3c | |||
| 3881a6659e | |||
| a567cc2222 | |||
| 6a9b2bac4a | |||
| 87542f4a56 | |||
| 32b47cd21e | |||
| bf75e1c062 | |||
| 97fccfa34b | |||
| 1ed32fe71c | |||
| 3ce8f251a1 | |||
| e2ad38f297 | |||
| 993303bfa4 | |||
| 50d9460f63 | |||
| 4b02b57c07 | |||
| 1fc9382ce9 | |||
| ea43e67fe8 | |||
| dd28a41e17 | |||
| b11a273d65 | |||
| d4ee25b004 | |||
| a2b7719100 | |||
| 1e6cde4d98 | |||
| 34f627d146 | |||
| 54accd4394 | |||
| 63557fba56 | |||
| 7a4be158c2 | |||
| 810e12bd22 | |||
| 066f7ad8c1 | |||
| e52a654731 | |||
| 370879f636 | |||
| 170a511654 | |||
| 679afe1bc4 | |||
| 8b5cfff24a | |||
| 27de97031e | |||
| 8ee874da14 | |||
| 11c783f088 | |||
| a3cb31291f | |||
| 6a43b86912 | |||
| 21bb535ee0 | |||
| 9ea948b825 | |||
| fe2fad9378 | |||
| d566ffd9fa | |||
| 370b23f38f | |||
| 253ee696be | |||
| e08c6f79bc | |||
| 4240319fef | |||
| e1aaa2415b | |||
| e71eb56630 | |||
| 38496f2971 | |||
| d1c7d8d9f6 | |||
| 36fdfd672f | |||
| 55c0f61189 | |||
| 053e317850 | |||
| 38296bf292 | |||
| f0ba4564cc | |||
| 21ec70214d | |||
| 6d1a8376ba | |||
| 0ca83fe152 | |||
| 2301c407a2 | |||
| d6096431bd | |||
| d7532d5b83 | |||
| c7d805f8df | |||
| d78ab30cdf | |||
| c123f77195 | |||
| a60bc78e23 | |||
| 78ee107e85 | |||
| 12c3310451 | |||
| d525d8f603 | |||
| 337d1095dc | |||
| fab40cb6b3 | |||
| f4cdc1aecd | |||
| f702e3245a | |||
| d890ba4f43 | |||
| d929ed411f | |||
| 55daa28d74 | |||
| 2bab12aad1 | |||
| 80fb376132 | |||
| 1d557f1065 | |||
| 30df3df8cf | |||
| 02b4655a16 | |||
| debf0158d4 | |||
| 0f730c1948 | |||
| fa7e324fe0 | |||
| e2313e6a3d | |||
| 2ce8c42323 | |||
| 684e65adaa | |||
| a8fc3fb2f1 | |||
| 68bcdb2f88 | |||
| af3627bccb | |||
| 4cbe032363 | |||
| 5e4b3cf0d2 | |||
| 593af1048b | |||
| ae00ecb773 | |||
| da83e42172 | |||
| 2895d53f8e | |||
| 10d1f22ec3 | |||
| 4ed1e64a61 | |||
| 6402936285 | |||
| e01e5c145a | |||
| 56f6d82c8f | |||
| 3e79cf0c12 | |||
| efc09657a8 | |||
| 64390c3e01 | |||
| 513edb802d | |||
| 52c35b8e3c | |||
| cf1c25031c | |||
| 7b9f18867a | |||
| 0985b4dbe8 | |||
| 772fb721ae | |||
| 1ef1c795c1 | |||
| 6d956566c5 | |||
| edec5bb25f | |||
| 3534f65f0e | |||
| 6fbea9c8a4 | |||
| 18bba5da3d | |||
| 952270e1ba | |||
| adc353cdcc | |||
| 0c180e6ee5 | |||
| fdd9c329b1 | |||
| 5b80459b37 | |||
| 1b646a6e00 | |||
| cf970efbec | |||
| 4020cdac69 | |||
| 2415c2ffe8 | |||
| d41502ea19 | |||
| f5d0ef4005 | |||
| c4a89ecf61 | |||
| 71eb25e561 | |||
| 486a6683fd | |||
| 2175d8d87c | |||
| f463bff49e | |||
| a817e2b046 | |||
| 3539e36bde | |||
| 6930a9ffe1 | |||
| e0a44502b1 | |||
| 19e1bd5586 | |||
| ea65ba02f1 | |||
| 8406e48009 | |||
| a8f1d11cbc | |||
| f245a4a9c6 | |||
| 597529a16d | |||
| 9b9dba05c2 | |||
| 2d0bbc824f | |||
| fa523c673f | |||
| da1a4ba393 | |||
| e9c9712e52 | |||
| 78561ca659 | |||
| 1ad87383e3 | |||
| c29ac1549f | |||
| f09eeb19e5 | |||
| 4b7b2c78a2 | |||
| 414af6bdb0 | |||
| df7288b275 | |||
| ce80953086 | |||
| d1344dab71 | |||
| 4f2ba4ae76 | |||
| 6bd525c3b4 | |||
| 341671a612 | |||
| 9161aa1556 | |||
| 70e9fbabce | |||
| a2c00deba2 | |||
| 9b4ef9d1d7 | |||
| 3baee0c14e | |||
| 0508bf43d1 | |||
| bd279d1ad7 | |||
| 4d55a66307 | |||
| 9481e01581 | |||
| fe91bf9620 | |||
| d812ba379b | |||
| e1cc7f3c83 | |||
| f50d5d2cd1 | |||
| b3987b0ad5 | |||
| 243946a189 | |||
| 63fbbc5603 | |||
| fcb857df69 | |||
| dabbc31c09 | |||
| 997bfa3dd5 | |||
| 50eca8aab5 | |||
| 6e4a2e4d5e | |||
| 40e9938885 | |||
| 5bc8ca2266 | |||
| 4cdbfbfb86 | |||
| 01575d1f2e | |||
| 8f75c75b80 | |||
| ebc084f9ea | |||
| 626efaf5cf | |||
| 096ce99588 | |||
| 9ce103b31b | |||
| 13cbd84b58 | |||
| a8912dff41 | |||
| 8b773614ba | |||
| d04f04f382 | |||
| 9a44dae4f9 | |||
| 07665dd93e | |||
| eeca17e78b | |||
| f91264bc94 | |||
| 10b7f63f9f | |||
| f2dff2d173 | |||
| aa49605ac4 |
88
.github/workflows/git-operations.yml
vendored
Normal file
88
.github/workflows/git-operations.yml
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
name: Git Operations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
operation:
|
||||
description: 'Operation to perform'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- create
|
||||
- remove
|
||||
default: 'create'
|
||||
|
||||
branch_name:
|
||||
description: 'Branch name to create or remove'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
base_branch:
|
||||
description: 'Base branch to work from (for create operation)'
|
||||
required: false
|
||||
type: string
|
||||
default: 'develop'
|
||||
|
||||
branding:
|
||||
description: 'Branding name'
|
||||
required: false
|
||||
type: string
|
||||
default: 'onlyoffice'
|
||||
|
||||
branding_url:
|
||||
description: 'Branding repository URL (relative to git host)'
|
||||
required: false
|
||||
type: string
|
||||
default: 'ONLYOFFICE/onlyoffice.git'
|
||||
|
||||
jobs:
|
||||
git-operations:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ONLYOFFICE/build_tools
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
# Install any Python dependencies if requirements.txt exists
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config --global user.name "GitHub Actions Bot"
|
||||
git config --global user.email "actions@github.com"
|
||||
|
||||
- name: Run Git Operations
|
||||
run: |
|
||||
cd ONLYOFFICE/build_tools/scripts/develop
|
||||
python git_operations.py ${{ inputs.operation }} "${{ inputs.branch_name }}" \
|
||||
--base-branch="${{ inputs.base_branch }}" \
|
||||
--branding="${{ inputs.branding }}" \
|
||||
--branding-url="${{ inputs.branding_url }}" \
|
||||
--modules="${{ inputs.modules }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Operation Summary
|
||||
run: |
|
||||
echo "## Git Operations Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Operation**: ${{ inputs.operation }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Branch Name**: ${{ inputs.branch_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Base Branch**: ${{ inputs.base_branch }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Branding**: ${{ inputs.branding }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Branding URL**: ${{ inputs.branding_url }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Modules**: ${{ inputs.modules }}" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ inputs.operation }}" = "remove" ] && [ "${{ inputs.force_remove }}" = "true" ]; then
|
||||
echo "- **Force Remove**: Yes" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -7,6 +7,7 @@ config
|
||||
*.*~
|
||||
**~
|
||||
*.DS_Store
|
||||
.idea
|
||||
scripts/license_checker/reports
|
||||
tests/puppeteer/node_modules
|
||||
tests/puppeteer/work_directory
|
||||
@ -14,3 +15,6 @@ tests/puppeteer/package.json
|
||||
tests/puppeteer/package-lock.json
|
||||
scripts/sdkjs_common/jsdoc/node_modules
|
||||
scripts/sdkjs_common/jsdoc/package-lock.json
|
||||
tools/linux/python3/
|
||||
tools/linux/python3.tar.gz
|
||||
tools/linux/sysroot/sysroot_ubuntu_1604
|
||||
|
||||
32
Dockerfile
32
Dockerfile
@ -1,15 +1,33 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ENV TZ=Etc/UTC
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN echo 'keyboard-configuration keyboard-configuration/layoutcode string us' | debconf-set-selections && \
|
||||
echo 'keyboard-configuration keyboard-configuration/modelcode string pc105' | debconf-set-selections
|
||||
|
||||
RUN apt-get -y update && \
|
||||
apt-get -y install python \
|
||||
python3 \
|
||||
sudo
|
||||
RUN rm /usr/bin/python && ln -s /usr/bin/python2 /usr/bin/python
|
||||
apt-get -y install tar \
|
||||
sudo \
|
||||
wget
|
||||
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.30.0/cmake-3.30.0-linux-x86_64.tar.gz && \
|
||||
tar -xzf cmake-3.30.0-linux-x86_64.tar.gz -C /opt && \
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/cmake /usr/local/bin/cmake && \
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/ctest /usr/local/bin/ctest && \
|
||||
rm cmake-3.30.0-linux-x86_64.tar.gz
|
||||
|
||||
ADD . /build_tools
|
||||
WORKDIR /build_tools
|
||||
|
||||
CMD cd tools/linux && \
|
||||
python3 ./automate.py
|
||||
RUN mkdir -p /opt/python3 && \
|
||||
wget -P /opt/python3/ https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/python3.tar.gz && \
|
||||
tar -xzf /opt/python3/python3.tar.gz -C /opt/python3 --strip-components=1
|
||||
|
||||
ENV PATH="/opt/python3/bin:${PATH}"
|
||||
|
||||
RUN ln -s /opt/python3/bin/python3.10 /usr/bin/python
|
||||
|
||||
CMD ["sh", "-c", "cd tools/linux && python3 ./automate.py"]
|
||||
|
||||
@ -8,8 +8,8 @@ necessary for the compilation process, all the dependencies required for the
|
||||
correct work, as well as to get the latest version of
|
||||
**ONLYOFFICE products** source code and build all their components.
|
||||
|
||||
**Important!** We can only guarantee the correct work of the products built from
|
||||
the `master` branch.
|
||||
**Important!** We can only guarantee the correct work of the products built
|
||||
from the `master` branch.
|
||||
|
||||
## How to use - Linux
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ parser.add_option("--clean", action="store", type="string", dest="clean", defaul
|
||||
parser.add_option("--module", action="store", type="string", dest="module", default="builder", help="defines what modules to build. You can specify several of them, e.g. --module 'core desktop builder server mobile'")
|
||||
parser.add_option("--develop", action="store", type="string", dest="develop", default="0", help="defines develop mode")
|
||||
parser.add_option("--beta", action="store", type="string", dest="beta", default="0", help="defines beta mode")
|
||||
parser.add_option("--platform", action="store", type="string", dest="platform", default="native", help="defines the destination platform for your build ['win_64', 'win_32', 'win_64_xp', 'win_32_xp', 'linux_64', 'linux_32', 'mac_64', 'ios', 'android_arm64_v8a', 'android_armv7', 'android_x86', 'android_x86_64'; combinations: 'native': your current system (windows/linux/mac only); 'all': all available systems; 'windows': win_64 win_32 win_64_xp win_32_xp; 'linux': linux_64 linux_32; 'mac': mac_64; 'android': android_arm64_v8a android_armv7 android_x86 android_x86_64]")
|
||||
parser.add_option("--platform", action="store", type="string", dest="platform", default="native", help="defines the destination platform for your build ['win_64', 'win_32', 'win_64_xp', 'win_32_xp', 'win_arm64', 'linux_64', 'linux_32', 'mac_64', 'ios', 'android_arm64_v8a', 'android_armv7', 'android_x86', 'android_x86_64'; combinations: 'native': your current system (windows/linux/mac only); 'all': all available systems; 'windows': win_64 win_32 win_64_xp win_32_xp; 'linux': linux_64 linux_32; 'mac': mac_64; 'android': android_arm64_v8a android_armv7 android_x86 android_x86_64]")
|
||||
parser.add_option("--config", action="store", type="string", dest="config", default="", help="provides ability to specify additional parameters for qmake")
|
||||
parser.add_option("--qt-dir", action="store", type="string", dest="qt-dir", default="", help="defines qmake directory path. qmake can be found in qt-dir/compiler/bin directory")
|
||||
parser.add_option("--qt-dir-xp", action="store", type="string", dest="qt-dir-xp", default="", help="defines qmake directory path for Windows XP. qmake can be found in 'qt-dir/compiler/bin directory")
|
||||
@ -27,7 +27,7 @@ parser.add_option("--db-pass", action="store", type="string", dest="db-pass", de
|
||||
parser.add_option("--compiler", action="store", type="string", dest="compiler", default="", help="defines compiler name. It is not recommended to use it as it's defined automatically (msvc2015, msvc2015_64, gcc, gcc_64, clang, clang_64, etc)")
|
||||
parser.add_option("--no-apps", action="store", type="string", dest="no-apps", default="0", help="disables building desktop apps that use qt")
|
||||
parser.add_option("--themesparams", action="store", type="string", dest="themesparams", default="", help="provides settings for generating presentation themes thumbnails")
|
||||
parser.add_option("--git-protocol", action="store", type="string", dest="git-protocol", default="https", help="can be used only if update is set to true - 'https', 'ssh'")
|
||||
parser.add_option("--git-protocol", action="store", type="string", dest="git-protocol", default="auto", help="can be used only if update is set to true - 'https', 'ssh'")
|
||||
parser.add_option("--branding", action="store", type="string", dest="branding", default="", help="provides branding path")
|
||||
parser.add_option("--branding-name", action="store", type="string", dest="branding-name", default="", help="provides branding name")
|
||||
parser.add_option("--branding-url", action="store", type="string", dest="branding-url", default="", help="provides branding url")
|
||||
@ -42,6 +42,8 @@ parser.add_option("--vs-version", action="store", type="string", dest="vs-versio
|
||||
parser.add_option("--vs-path", action="store", type="string", dest="vs-path", default="", help="path to vcvarsall")
|
||||
parser.add_option("--siteUrl", action="store", type="string", dest="siteUrl", default="127.0.0.1", help="site url")
|
||||
parser.add_option("--multiprocess", action="store", type="string", dest="multiprocess", default="1", help="provides ability to specify single process for make")
|
||||
parser.add_option("--sysroot", action="store", type="string", dest="sysroot", default="0", help="provides ability to use sysroot (ubuntu 16.04) to build c++ code. If value is \"1\", then the sysroot from tools/linux/sysroot will be used, and if it is not there, it will download it and unpack it. You can also set value as the path to the your own sysroot (rarely used). Only for linux")
|
||||
parser.add_option("--qemu-win-arm64-dir", action="store", type="string", dest="qemu-win-arm64-dir", default="", help="dir to qemu virtual machine for win_arm64 cross build. It should contains start.bat. More info in tools/win/qemu.")
|
||||
|
||||
(options, args) = parser.parse_args(arguments)
|
||||
configOptions = vars(options)
|
||||
|
||||
4
defaults
4
defaults
@ -1,3 +1,3 @@
|
||||
sdkjs-plugin="photoeditor, macros, ocr, translator, thesaurus, youtube, highlightcode, zotero"
|
||||
sdkjs-plugin-server="speech, zotero, mendeley, speechrecognition, drawio"
|
||||
sdkjs-plugin="ai, photoeditor, ocr, translator, thesaurus, youtube, highlightcode"
|
||||
sdkjs-plugin-server="speech, zotero, mendeley, speechrecognition"
|
||||
sdkjs-addons="sdkjs-forms"
|
||||
|
||||
@ -6,6 +6,10 @@ but don't want to compile pretty compilcated core product to make those changes.
|
||||
|
||||
## System requirements
|
||||
|
||||
**Note**: ARM-based architectures are currently **NOT** supported;
|
||||
attempting to run the images on ARM devices may result in startup failures
|
||||
or other runtime issues.
|
||||
|
||||
### Windows
|
||||
|
||||
You need the latest
|
||||
|
||||
@ -8,7 +8,7 @@ import run_server
|
||||
import config
|
||||
import base
|
||||
|
||||
git_dir = sys.argv[1];
|
||||
git_dir = sys.argv[1]
|
||||
|
||||
base.print_info('argv :'+' '.join(sys.argv))
|
||||
base.cmd_in_dir(git_dir + '/build_tools/', 'python3', ['configure.py', '--develop', '1'] + sys.argv[2:])
|
||||
@ -18,7 +18,7 @@ config.parse_defaults()
|
||||
|
||||
if base.is_exist(git_dir + "/server/FileConverter/bin/fonts.log"):
|
||||
base.print_info('remove font cache to regenerate fonts in external sdkjs volume')
|
||||
base.delete_file(git_dir + "/server/FileConverter/bin/fonts.log");
|
||||
base.delete_file(git_dir + "/server/FileConverter/bin/fonts.log")
|
||||
|
||||
# external server volume
|
||||
if base.is_exist(sys.argv[1] + '/server/DocService/package.json'):
|
||||
@ -28,7 +28,7 @@ if base.is_exist(sys.argv[1] + '/server/DocService/package.json'):
|
||||
base.replaceInFileRE("/etc/supervisor/conf.d/ds-converter.conf", "command=.*", "command=node " + git_dir + "/server/FileConverter/sources/convertermaster.js")
|
||||
base.replaceInFileRE("/app/ds/setup/config/supervisor/ds/ds-converter.conf", "command=.*", "command=node " + git_dir + "/server/FileConverter/sources/convertermaster.js")
|
||||
base.print_info('run_server.run_docker_server')
|
||||
run_server.run_docker_server();
|
||||
run_server.run_docker_server()
|
||||
else:
|
||||
#Fix theme generation for external sdkjs volume
|
||||
if base.is_exist(git_dir + "/server/FileConverter/bin/DoctRenderer.config"):
|
||||
|
||||
5
make.py
5
make.py
@ -19,8 +19,6 @@ import make_common
|
||||
import develop
|
||||
import argparse
|
||||
|
||||
base.check_python()
|
||||
|
||||
parser = argparse.ArgumentParser(description="options")
|
||||
parser.add_argument("--build-only-branding", action="store_true")
|
||||
args = parser.parse_args()
|
||||
@ -30,6 +28,7 @@ if (args.build_only_branding):
|
||||
|
||||
# parse configuration
|
||||
config.parse()
|
||||
base.check_python()
|
||||
|
||||
base_dir = base.get_script_dir(__file__)
|
||||
|
||||
@ -92,6 +91,8 @@ if config.check_option("module", "desktop"):
|
||||
config.extend_option("config", "updmodule")
|
||||
base.set_env("DESKTOP_URL_UPDATES_MAIN_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/appcast.json")
|
||||
base.set_env("DESKTOP_URL_UPDATES_DEV_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/appcastdev.json")
|
||||
base.set_env("DESKTOP_URL_INSTALL_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/distrib/onlyoffice/<file>")
|
||||
base.set_env("DESKTOP_URL_INSTALL_DEV_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/onlineinstallerdev/<file>")
|
||||
|
||||
# build
|
||||
build_sln.make()
|
||||
|
||||
@ -10,15 +10,17 @@ import package_utils as utils
|
||||
# parse
|
||||
parser = argparse.ArgumentParser(description="Build packages.")
|
||||
parser.add_argument("-P", "--platform", dest="platform", type=str,
|
||||
action="store", help="Defines platform", required=True)
|
||||
parser.add_argument("-T", "--targets", dest="targets", type=str, nargs="+",
|
||||
action="store", help="Defines targets", required=True)
|
||||
parser.add_argument("-R", "--branding", dest="branding", type=str,
|
||||
action="store", help="Provides branding path")
|
||||
action="store", help="Defines platform", required=True)
|
||||
parser.add_argument("-T", "--targets", dest="targets", type=str, nargs="+",
|
||||
action="store", help="Defines targets", required=True)
|
||||
parser.add_argument("-V", "--version", dest="version", type=str,
|
||||
action="store", help="Defines version")
|
||||
action="store", help="Defines version")
|
||||
parser.add_argument("-B", "--build", dest="build", type=str,
|
||||
action="store", help="Defines build")
|
||||
action="store", help="Defines build")
|
||||
parser.add_argument("-H", "--branch", dest="branch", type=str,
|
||||
action="store", help="Defines branch")
|
||||
parser.add_argument("-R", "--branding", dest="branding", type=str,
|
||||
action="store", help="Provides branding path")
|
||||
args = parser.parse_args()
|
||||
|
||||
# vars
|
||||
@ -29,13 +31,20 @@ common.targets = args.targets
|
||||
common.clean = "clean" in args.targets
|
||||
common.sign = "sign" in args.targets
|
||||
common.deploy = "deploy" in args.targets
|
||||
common.version = args.version if args.version else utils.get_env("BUILD_VERSION", "0.0.0")
|
||||
common.build = args.build if args.build else utils.get_env("BUILD_NUMBER", "0")
|
||||
if args.version: common.version = args.version
|
||||
else: common.version = utils.get_env("PRODUCT_VERSION", "0.0.0")
|
||||
utils.set_env("PRODUCT_VERSION", common.version)
|
||||
utils.set_env("BUILD_VERSION", common.version)
|
||||
if args.build: common.build = args.build
|
||||
else: common.build = utils.get_env("BUILD_NUMBER", "0")
|
||||
utils.set_env("BUILD_NUMBER", common.build)
|
||||
if args.branch: common.branch = args.branch
|
||||
else: common.branch = utils.get_env("BRANCH_NAME", "null")
|
||||
utils.set_env("BRANCH_NAME", common.branch)
|
||||
common.branding = args.branding
|
||||
common.timestamp = utils.get_timestamp()
|
||||
common.workspace_dir = utils.get_abspath(utils.get_script_dir(__file__) + "/..")
|
||||
common.branding_dir = utils.get_abspath(common.workspace_dir + "/" + args.branding) if args.branding else common.workspace_dir
|
||||
common.deploy_data = utils.get_path(common.workspace_dir + "/deploy.txt")
|
||||
common.summary = []
|
||||
utils.log("os_family: " + common.os_family)
|
||||
utils.log("platform: " + str(common.platform))
|
||||
@ -64,15 +73,14 @@ import package_mobile
|
||||
|
||||
# build
|
||||
utils.set_cwd(common.workspace_dir, verbose=True)
|
||||
utils.delete_file(common.deploy_data)
|
||||
if "core" in common.targets:
|
||||
package_core.make()
|
||||
if "closuremaps_opensource" in common.targets:
|
||||
if "closuremaps_sdkjs_opensource" in common.targets:
|
||||
package_core.deploy_closuremaps_sdkjs("opensource")
|
||||
package_core.deploy_closuremaps_webapps("opensource")
|
||||
if "closuremaps_commercial" in common.targets:
|
||||
if "closuremaps_sdkjs_commercial" in common.targets:
|
||||
package_core.deploy_closuremaps_sdkjs("commercial")
|
||||
package_core.deploy_closuremaps_webapps("commercial")
|
||||
if "closuremaps_webapps" in common.targets:
|
||||
package_core.deploy_closuremaps_webapps("opensource")
|
||||
if "desktop" in common.targets:
|
||||
package_desktop.make()
|
||||
if "builder" in common.targets:
|
||||
@ -83,6 +91,8 @@ if "server_enterprise" in common.targets:
|
||||
package_server.make("enterprise")
|
||||
if "server_developer" in common.targets:
|
||||
package_server.make("developer")
|
||||
if "server_prerequisites" in common.targets:
|
||||
package_server.make("prerequisites")
|
||||
if "mobile" in common.targets:
|
||||
package_mobile.make()
|
||||
|
||||
|
||||
476
scripts/base.py
476
scripts/base.py
@ -15,6 +15,8 @@ import stat
|
||||
import json
|
||||
|
||||
__file__script__path__ = os.path.dirname( os.path.realpath(__file__))
|
||||
icu_ver = "74"
|
||||
icu_ver_old = "58" # for win_xp support
|
||||
|
||||
# common functions --------------------------------------
|
||||
def get_script_dir(file=""):
|
||||
@ -39,6 +41,9 @@ def is_os_arm():
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_platform():
|
||||
return platform.machine().lower()
|
||||
|
||||
def is_python_64bit():
|
||||
return (struct.calcsize("P") == 8)
|
||||
|
||||
@ -69,7 +74,7 @@ def check_build_version(dir):
|
||||
version_number = version_number.replace("\n", "")
|
||||
set_env("PRODUCT_VERSION", version_number)
|
||||
if ("" == get_env("BUILD_NUMBER")):
|
||||
set_env("BUILD_NUMBER", "0")
|
||||
set_env("BUILD_NUMBER", "0")
|
||||
return
|
||||
|
||||
def print_info(info=""):
|
||||
@ -172,6 +177,13 @@ def find_file(path, pattern):
|
||||
for filename in fnmatch.filter(filenames, pattern):
|
||||
return os.path.join(root, filename)
|
||||
|
||||
def find_files(path, pattern):
|
||||
result = []
|
||||
for root, dirnames, filenames in os.walk(path):
|
||||
for filename in fnmatch.filter(filenames, pattern):
|
||||
result.append(os.path.join(root, filename))
|
||||
return result
|
||||
|
||||
def create_dir(path):
|
||||
path2 = get_path(path)
|
||||
if not os.path.exists(path2):
|
||||
@ -186,11 +198,11 @@ def move_dir(src, dst):
|
||||
delete_dir(src)
|
||||
return
|
||||
|
||||
def copy_dir(src, dst):
|
||||
def copy_dir(src, dst, symlinks=False):
|
||||
if is_dir(dst):
|
||||
delete_dir(dst)
|
||||
try:
|
||||
shutil.copytree(get_path(src), get_path(dst))
|
||||
shutil.copytree(get_path(src), get_path(dst), symlinks=symlinks)
|
||||
except:
|
||||
if ("windows" == host_platform()) and copy_dir_windows(src, dst):
|
||||
return
|
||||
@ -244,7 +256,7 @@ def delete_dir(path):
|
||||
|
||||
def copy_lib(src, dst, name):
|
||||
if (config.check_option("config", "bundle_dylibs")) and is_dir(src + "/" + name + ".framework"):
|
||||
copy_dir(src + "/" + name + ".framework", dst + "/" + name + ".framework")
|
||||
copy_dir(src + "/" + name + ".framework", dst + "/" + name + ".framework", symlinks=True)
|
||||
|
||||
if (config.check_option("config", "bundle_xcframeworks")) and is_dir(src + "/simulator/" + name + ".framework"):
|
||||
create_dir(dst + "/simulator")
|
||||
@ -253,9 +265,9 @@ def copy_lib(src, dst, name):
|
||||
if is_dir(dst + "/" + name + ".xcframework"):
|
||||
delete_dir(dst + "/" + name + ".xcframework")
|
||||
|
||||
cmd("xcodebuild", ["-create-xcframework",
|
||||
"-framework", dst + "/" + name + ".framework",
|
||||
"-framework", dst + "/simulator/" + name + ".framework",
|
||||
cmd("xcodebuild", ["-create-xcframework",
|
||||
"-framework", dst + "/" + name + ".framework",
|
||||
"-framework", dst + "/simulator/" + name + ".framework",
|
||||
"-output", dst + "/" + name + ".xcframework"])
|
||||
|
||||
delete_dir(dst + "/" + name + ".framework")
|
||||
@ -358,7 +370,7 @@ def writeFile(path, data):
|
||||
return
|
||||
|
||||
# system cmd methods ------------------------------------
|
||||
def cmd(prog, args=[], is_no_errors=False):
|
||||
def cmd(prog, args=[], is_no_errors=False):
|
||||
ret = 0
|
||||
if ("windows" == host_platform()):
|
||||
sub_args = args[:]
|
||||
@ -367,13 +379,13 @@ def cmd(prog, args=[], is_no_errors=False):
|
||||
else:
|
||||
command = prog
|
||||
for arg in args:
|
||||
command += (" \"" + arg + "\"")
|
||||
command += (" \"" + arg.replace('\"', '\\\"') + "\"")
|
||||
ret = subprocess.call(command, stderr=subprocess.STDOUT, shell=True)
|
||||
if ret != 0 and True != is_no_errors:
|
||||
sys.exit("Error (" + prog + "): " + str(ret))
|
||||
return ret
|
||||
|
||||
def cmd2(prog, args=[], is_no_errors=False):
|
||||
def cmd2(prog, args=[], is_no_errors=False):
|
||||
ret = 0
|
||||
command = prog if ("windows" != host_platform()) else get_path(prog)
|
||||
for arg in args:
|
||||
@ -403,7 +415,7 @@ def cmd_exe(prog, args, is_no_errors=False):
|
||||
else:
|
||||
command = prog
|
||||
for arg in args:
|
||||
command += (" \"" + arg + "\"")
|
||||
command += (" \"" + arg.replace('\"', '\\\"') + "\"")
|
||||
process = subprocess.Popen(command, stderr=subprocess.STDOUT, shell=True, env=env_dir)
|
||||
ret = process.wait()
|
||||
if ret != 0 and True != is_no_errors:
|
||||
@ -418,6 +430,13 @@ def cmd_in_dir(directory, prog, args=[], is_no_errors=False):
|
||||
os.chdir(cur_dir)
|
||||
return ret
|
||||
|
||||
def cmd_in_dir_qemu(platform, directory, prog, args=[], is_no_errors=False):
|
||||
if (platform == "linux_arm64"):
|
||||
return cmd_in_dir(directory, "qemu-aarch64", ["-L", "/usr/aarch64-linux-gnu", prog] + args, is_no_errors)
|
||||
if (platform == "linux_arm32"):
|
||||
return cmd_in_dir(directory, "qemu-arm", ["-L", "/usr/arm-linux-gnueabi", prog] + args, is_no_errors)
|
||||
return 0
|
||||
|
||||
def cmd_and_return_cwd(prog, args=[], is_no_errors=False):
|
||||
cur_dir = os.getcwd()
|
||||
ret = cmd(prog, args, is_no_errors)
|
||||
@ -426,16 +445,17 @@ def cmd_and_return_cwd(prog, args=[], is_no_errors=False):
|
||||
|
||||
def run_command(sCommand):
|
||||
popen = subprocess.Popen(sCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
result = {'stdout' : '', 'stderr' : ''}
|
||||
result = {'stdout' : '', 'stderr' : '', 'returncode' : 0}
|
||||
try:
|
||||
stdout, stderr = popen.communicate()
|
||||
popen.wait()
|
||||
result['stdout'] = stdout.strip().decode('utf-8', errors='ignore')
|
||||
result['stderr'] = stderr.strip().decode('utf-8', errors='ignore')
|
||||
result['returncode'] = popen.returncode
|
||||
finally:
|
||||
popen.stdout.close()
|
||||
popen.stderr.close()
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def run_command_in_dir(directory, sCommand):
|
||||
@ -450,7 +470,7 @@ def run_command_in_dir(directory, sCommand):
|
||||
if (host == 'windows'):
|
||||
os.chdir(cur_dir)
|
||||
return ret
|
||||
|
||||
|
||||
def exec_command_in_dir(directory, sCommand):
|
||||
host = host_platform()
|
||||
if (host == 'windows'):
|
||||
@ -496,12 +516,58 @@ def set_cwd(dir):
|
||||
return
|
||||
|
||||
# git ---------------------------------------------------
|
||||
def git_get_origin():
|
||||
cur_dir = os.getcwd()
|
||||
os.chdir(get_script_dir() + "/../")
|
||||
ret = run_command("git config --get remote.origin.url")["stdout"]
|
||||
os.chdir(cur_dir)
|
||||
return ret
|
||||
|
||||
def git_get_base_url():
|
||||
"""Get the base URL for git operations, with fallback to GitHub"""
|
||||
origin = git_get_origin()
|
||||
if origin:
|
||||
# Extract base URL from origin
|
||||
if origin.startswith("https://"):
|
||||
# For HTTPS URLs like https://git.example.com/owner/repo.git
|
||||
parts = origin.split("/")
|
||||
if len(parts) >= 4:
|
||||
return "/".join(parts[:3]) + "/"
|
||||
elif ":" in origin and "@" in origin:
|
||||
# For SSH URLs like git@git.example.com:owner/repo.git
|
||||
at_pos = origin.find("@")
|
||||
colon_pos = origin.find(":", at_pos)
|
||||
if at_pos != -1 and colon_pos != -1:
|
||||
host = origin[at_pos+1:colon_pos]
|
||||
return f"https://{host}/"
|
||||
|
||||
# Fallback to GitHub
|
||||
return "https://github.com/"
|
||||
|
||||
def git_is_ssh():
|
||||
git_protocol = config.option("git-protocol")
|
||||
if (git_protocol == "https"):
|
||||
return False
|
||||
if (git_protocol == "ssh"):
|
||||
return True
|
||||
origin = git_get_origin()
|
||||
if (git_protocol == "auto") and (origin.find(":ONLYOFFICE/") != -1):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_ssh_base_url():
|
||||
cur_origin = git_get_origin()
|
||||
ind = cur_origin.find(":ONLYOFFICE/")
|
||||
if (ind == -1):
|
||||
return "git@github.com:ONLYOFFICE/"
|
||||
return cur_origin[:ind+12]
|
||||
|
||||
def git_update(repo, is_no_errors=False, is_current_dir=False, git_owner=""):
|
||||
print("[git] update: " + repo)
|
||||
owner = git_owner if git_owner else "ONLYOFFICE"
|
||||
url = "https://github.com/" + owner + "/" + repo + ".git"
|
||||
if config.option("git-protocol") == "ssh":
|
||||
url = "git@github.com:ONLYOFFICE/" + repo + ".git"
|
||||
url = git_get_base_url() + owner + "/" + repo + ".git"
|
||||
if git_is_ssh():
|
||||
url = get_ssh_base_url() + repo + ".git"
|
||||
folder = get_script_dir() + "/../../" + repo
|
||||
if is_current_dir:
|
||||
folder = repo
|
||||
@ -534,10 +600,12 @@ def get_repositories():
|
||||
result.update(get_sdkjs_addons())
|
||||
result["onlyoffice.github.io"] = [False, False]
|
||||
result["web-apps"] = [False, False]
|
||||
result.update(get_web_apps_addons())
|
||||
result["dictionaries"] = [False, False]
|
||||
result["core-fonts"] = [False, False]
|
||||
|
||||
if config.check_option("module", "server"):
|
||||
result.update(get_web_apps_addons())
|
||||
|
||||
if config.check_option("module", "builder"):
|
||||
result["document-templates"] = [False, False]
|
||||
|
||||
@ -569,9 +637,9 @@ def get_branding_repositories(checker):
|
||||
|
||||
def create_pull_request(branches_to, repo, is_no_errors=False, is_current_dir=False):
|
||||
print("[git] create pull request: " + repo)
|
||||
url = "https://github.com/ONLYOFFICE/" + repo + ".git"
|
||||
if config.option("git-protocol") == "ssh":
|
||||
url = "git@github.com:ONLYOFFICE/" + repo + ".git"
|
||||
url = git_get_base_url() + "ONLYOFFICE/" + repo + ".git"
|
||||
if git_is_ssh():
|
||||
url = get_ssh_base_url() + repo + ".git"
|
||||
folder = get_script_dir() + "/../../" + repo
|
||||
if is_current_dir:
|
||||
folder = repo
|
||||
@ -596,7 +664,7 @@ def create_pull_request(branches_to, repo, is_no_errors=False, is_current_dir=Fa
|
||||
cmd("git", ["merge", "--abort"], is_no_errors)
|
||||
else:
|
||||
cmd("git", ["push"], is_no_errors)
|
||||
|
||||
|
||||
os.chdir(old_cur)
|
||||
return
|
||||
|
||||
@ -608,7 +676,7 @@ def update_repositories(repositories):
|
||||
git_update(repo, value[0], False)
|
||||
else:
|
||||
if is_dir(current_dir + "/.git"):
|
||||
delete_dir_with_access_error(current_dir);
|
||||
delete_dir_with_access_error(current_dir)
|
||||
delete_dir(current_dir)
|
||||
if not is_dir(current_dir):
|
||||
create_dir(current_dir)
|
||||
@ -630,9 +698,12 @@ def get_prefix_cross_compiler_arm64():
|
||||
return ""
|
||||
|
||||
def get_gcc_version():
|
||||
gcc_path = "gcc"
|
||||
if config.option("sysroot") != "":
|
||||
gcc_path = config.option("sysroot") + "/usr/bin/gcc"
|
||||
gcc_version_major = 4
|
||||
gcc_version_minor = 0
|
||||
gcc_version_str = run_command("gcc -dumpfullversion -dumpversion")['stdout']
|
||||
gcc_version_str = run_command(gcc_path + " -dumpfullversion -dumpversion")['stdout']
|
||||
if (gcc_version_str != ""):
|
||||
try:
|
||||
gcc_ver = gcc_version_str.split(".")
|
||||
@ -670,6 +741,14 @@ def qt_setup(platform):
|
||||
if ("gcc_arm" == compiler_platform):
|
||||
qt_dir = config.option("qt-dir") + "/gcc"
|
||||
|
||||
# OVERRIDE IF NEEDED
|
||||
set_env("QT_QMAKE_ADDON", "")
|
||||
if platform == "win_arm64" and not is_dir(qt_dir):
|
||||
override_qt_directory = os.path.abspath(os.path.dirname(__file__) + "/../tools/win/arm64/qt_build/Qt-5.15.2/win_arm64")
|
||||
if is_dir(override_qt_directory):
|
||||
qt_dir = os.path.abspath(override_qt_directory).replace("\\", "/")
|
||||
set_env("QT_QMAKE_ADDON", "-spec win32-arm64-msvc2017")
|
||||
|
||||
set_env("QT_DEPLOY", qt_dir + "/bin")
|
||||
|
||||
if ("linux_arm64" == platform):
|
||||
@ -678,7 +757,7 @@ def qt_setup(platform):
|
||||
set_env("ARM64_TOOLCHAIN_BIN", cross_compiler_arm64)
|
||||
set_env("ARM64_TOOLCHAIN_BIN_PREFIX", get_prefix_cross_compiler_arm64())
|
||||
|
||||
return qt_dir
|
||||
return qt_dir
|
||||
|
||||
def qt_version():
|
||||
qt_dir = get_env("QT_DEPLOY")
|
||||
@ -738,8 +817,9 @@ def qt_config(platform):
|
||||
if (-1 != platform.find("xp")):
|
||||
config_param += " build_xp"
|
||||
if ("ios" == platform):
|
||||
set_env("BITCODE_GENERATION_MODE", "bitcode")
|
||||
set_env("ENABLE_BITCODE", "YES")
|
||||
if (config.check_option("bitcode", "yes")):
|
||||
set_env("BITCODE_GENERATION_MODE", "bitcode")
|
||||
set_env("ENABLE_BITCODE", "YES")
|
||||
config_param = config_param.replace("desktop", "")
|
||||
config_param += " iphoneos device"
|
||||
if (-1 == config_param_lower.find("debug")):
|
||||
@ -763,6 +843,9 @@ def qt_config(platform):
|
||||
if ("linux_arm64" == platform):
|
||||
config_param += " linux_arm64"
|
||||
|
||||
if ("win_arm64" == platform):
|
||||
config_param += " win_arm64"
|
||||
|
||||
config_param += qt_config_platform_addon(platform)
|
||||
return config_param
|
||||
|
||||
@ -787,6 +870,12 @@ def qt_config_as_param(value):
|
||||
|
||||
def qt_copy_lib(lib, dir):
|
||||
qt_dir = get_env("QT_DEPLOY")
|
||||
|
||||
# TODO: remove version from library name
|
||||
qt_major = qt_major_version()
|
||||
if ("5" != qt_major):
|
||||
lib = lib.replace("Qt5", "Qt" + qt_major)
|
||||
|
||||
if ("windows" == host_platform()):
|
||||
if ("" == qt_dst_postfix()):
|
||||
copy_lib(qt_dir, dir, lib)
|
||||
@ -795,7 +884,7 @@ def qt_copy_lib(lib, dir):
|
||||
else:
|
||||
src_file = qt_dir + "/../lib/lib" + lib + ".so." + qt_version()
|
||||
if (is_file(src_file)):
|
||||
copy_file(src_file, dir + "/lib" + lib + ".so." + qt_major_version())
|
||||
copy_file(src_file, dir + "/lib" + lib + ".so." + qt_major)
|
||||
else:
|
||||
libFramework = lib
|
||||
libFramework = libFramework.replace("Qt5", "Qt")
|
||||
@ -819,9 +908,24 @@ def _check_icu_common(dir, out):
|
||||
return isExist
|
||||
|
||||
def qt_copy_icu(out):
|
||||
tests = [get_env("QT_DEPLOY") + "/../lib", "/lib", "/lib/x86_64-linux-gnu", "/lib64", "/lib64/x86_64-linux-gnu"]
|
||||
tests += ["/usr/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib64", "/usr/lib64/x86_64-linux-gnu"]
|
||||
tests += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"]
|
||||
tests = [get_env("QT_DEPLOY") + "/../lib"]
|
||||
prefix = ""
|
||||
postfixes = [""]
|
||||
|
||||
# TODO add for linux arm desktop build
|
||||
if config.option("sysroot") != "":
|
||||
prefix = config.option("sysroot")
|
||||
else:
|
||||
prefix = ""
|
||||
|
||||
postfixes += ["/x86_64-linux-gnu"]
|
||||
postfixes += ["/i386-linux-gnu"]
|
||||
|
||||
for postfix in postfixes:
|
||||
tests += [prefix + "/lib" + postfix]
|
||||
tests += [prefix + "/lib64" + postfix]
|
||||
tests += [prefix + "/usr/lib" + postfix]
|
||||
tests += [prefix + "/usr/lib64" + postfix]
|
||||
|
||||
for test in tests:
|
||||
if (_check_icu_common(test, out)):
|
||||
@ -833,7 +937,7 @@ def qt_copy_plugin(name, out):
|
||||
src = get_env("QT_DEPLOY") + "/../plugins/" + name
|
||||
if not is_dir(src):
|
||||
return
|
||||
|
||||
|
||||
copy_dir(src, out + "/" + name)
|
||||
|
||||
if ("windows" == host_platform()):
|
||||
@ -845,7 +949,7 @@ def qt_copy_plugin(name, out):
|
||||
else:
|
||||
delete_file(fileCheck)
|
||||
for file in glob.glob(out + "/" + name + "/*.pdb"):
|
||||
delete_file(file)
|
||||
delete_file(file)
|
||||
return
|
||||
|
||||
def qt_dst_postfix():
|
||||
@ -910,14 +1014,14 @@ def generate_doctrenderer_config(path, root, product, vendor = "", dictionaries
|
||||
file.close()
|
||||
return
|
||||
|
||||
def generate_plist_framework_folder(file):
|
||||
def generate_plist(file, platform):
|
||||
bundle_id_url = "com.onlyoffice."
|
||||
if ("" != get_env("PUBLISHER_BUNDLE_ID")):
|
||||
bundle_id_url = get_env("PUBLISHER_BUNDLE_ID")
|
||||
bundle_creator = "Ascensio System SIA"
|
||||
if ("" != get_env("PUBLISHER_NAME")):
|
||||
bundle_creator = get_env("PUBLISHER_NAME")
|
||||
|
||||
|
||||
bundle_version_natural = readFile(get_script_dir() + "/../../core/Common/version.txt").split(".")
|
||||
bundle_version = []
|
||||
for n in bundle_version_natural:
|
||||
@ -944,11 +1048,14 @@ def generate_plist_framework_folder(file):
|
||||
content += "\t<string>????</string>\n"
|
||||
content += "\t<key>CFBundleVersion</key>\n"
|
||||
content += "\t<string>" + bundle_version[0] + "." + bundle_version[1] + "." + bundle_version[2] + "</string>\n"
|
||||
content += "\t<key>MinimumOSVersion</key>\n"
|
||||
content += "\t<string>13.0</string>\n"
|
||||
if platform.find("ios") == 0:
|
||||
content += "\t<key>MinimumOSVersion</key>\n"
|
||||
content += "\t<string>13.0</string>\n"
|
||||
content += "</dict>\n"
|
||||
content += "</plist>"
|
||||
|
||||
if platform.find("mac") == 0:
|
||||
file += "/Resources"
|
||||
fileDst = file + "/Info.plist"
|
||||
if is_file(fileDst):
|
||||
delete_file(fileDst)
|
||||
@ -958,7 +1065,33 @@ def generate_plist_framework_folder(file):
|
||||
fileInfo.close()
|
||||
return
|
||||
|
||||
def generate_plist(path):
|
||||
def generate_xcprivacy(file, platform):
|
||||
content = \
|
||||
"""<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
\t<key>NSPrivacyTracking</key>
|
||||
\t<false/>
|
||||
\t<key>NSPrivacyCollectedDataTypes</key>
|
||||
\t<array/>
|
||||
\t<key>NSPrivacyTrackingDomains</key>
|
||||
\t<array/>
|
||||
\t<key>NSPrivacyAccessedAPITypes</key>
|
||||
\t<array/>
|
||||
</dict>
|
||||
</plist>"""
|
||||
fileDst = os.path.join(file, "PrivacyInfo.xcprivacy")
|
||||
fileInfo = codecs.open(fileDst, "w", "utf-8")
|
||||
fileInfo.write(content)
|
||||
fileInfo.close()
|
||||
return
|
||||
|
||||
def for_each_framework(path, platform, callbacks, max_depth=512):
|
||||
if not config.check_option("config", "bundle_dylibs"):
|
||||
return
|
||||
if max_depth == 0:
|
||||
return
|
||||
src_folder = path
|
||||
if ("/" != path[-1:]):
|
||||
src_folder += "/"
|
||||
@ -966,9 +1099,10 @@ def generate_plist(path):
|
||||
for file in glob.glob(src_folder):
|
||||
if (is_dir(file)):
|
||||
if file.endswith(".framework"):
|
||||
generate_plist_framework_folder(file)
|
||||
for callback in callbacks:
|
||||
callback(file, platform)
|
||||
else:
|
||||
generate_plist(file)
|
||||
for_each_framework(file, platform, callbacks, max_depth - 1)
|
||||
return
|
||||
|
||||
def correct_bundle_identifier(bundle_identifier):
|
||||
@ -1167,65 +1301,95 @@ def get_file_last_modified_url(url):
|
||||
key = key.upper()
|
||||
if key == "LAST-MODIFIED":
|
||||
retvalue = value
|
||||
|
||||
|
||||
return retvalue
|
||||
|
||||
def mac_change_rpath_binary(bin, old, new):
|
||||
cmd("install_name_tool", ["-change", old, new, bin], True)
|
||||
|
||||
def mac_change_rpath_library(lib_name, old, new):
|
||||
# converts library name to actual library file name (dylib or binary file in framework)
|
||||
def lib_name_to_file_name(lib_name):
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
lib = lib_name + ".framework/" + lib_name
|
||||
else:
|
||||
lib = "lib" + lib_name + ".dylib"
|
||||
return lib
|
||||
mac_change_rpath_binary(lib_name_to_file_name(lib_name), old, new)
|
||||
|
||||
def mac_correct_rpath_binary(path, libs):
|
||||
# if framework are built, instead of correcting lib paths add `@loader_path` to rpaths with `mac_add_loader_path_to_rpath()`
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
return
|
||||
|
||||
for lib in libs:
|
||||
cmd("install_name_tool", ["-change", "lib" + lib + ".dylib", "@rpath/lib" + lib + ".dylib", path], True)
|
||||
mac_change_rpath_binary(path, "lib" + lib + ".dylib", "@rpath/lib" + lib + ".dylib")
|
||||
return
|
||||
|
||||
def mac_correct_rpath_library(name, libs):
|
||||
return mac_correct_rpath_binary("./lib" + name + ".dylib", libs)
|
||||
|
||||
mac_icu_libs = ["icudata." + icu_ver, "icuuc." + icu_ver]
|
||||
def mac_correct_rpath_x2t(dir):
|
||||
cur_dir = os.getcwd()
|
||||
os.chdir(dir)
|
||||
mac_correct_rpath_library("icudata.58", [])
|
||||
mac_correct_rpath_library("icuuc.58", ["icudata.58"])
|
||||
mac_correct_rpath_library("UnicodeConverter", ["icuuc.58", "icudata.58"])
|
||||
mac_correct_rpath_library("icudata." + icu_ver, [])
|
||||
mac_correct_rpath_library("icuuc." + icu_ver, ["icudata." + icu_ver])
|
||||
mac_correct_rpath_library("UnicodeConverter", mac_icu_libs)
|
||||
mac_correct_rpath_library("kernel", ["UnicodeConverter"])
|
||||
mac_correct_rpath_library("kernel_network", ["UnicodeConverter", "kernel"])
|
||||
mac_correct_rpath_library("graphics", ["UnicodeConverter", "kernel"])
|
||||
mac_correct_rpath_library("doctrenderer", ["UnicodeConverter", "kernel", "kernel_network", "graphics"])
|
||||
mac_correct_rpath_library("doctrenderer", ["UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "DocxRenderer"])
|
||||
mac_correct_rpath_library("HtmlFile2", ["UnicodeConverter", "kernel", "kernel_network", "graphics"])
|
||||
mac_correct_rpath_library("EpubFile", ["UnicodeConverter", "kernel", "HtmlFile2", "graphics"])
|
||||
mac_correct_rpath_library("Fb2File", ["UnicodeConverter", "kernel", "graphics"])
|
||||
mac_correct_rpath_library("HtmlRenderer", ["UnicodeConverter", "kernel", "graphics"])
|
||||
mac_correct_rpath_library("PdfFile", ["UnicodeConverter", "kernel", "graphics", "kernel_network"])
|
||||
mac_correct_rpath_library("DjVuFile", ["UnicodeConverter", "kernel", "graphics", "PdfFile"])
|
||||
mac_correct_rpath_library("XpsFile", ["UnicodeConverter", "kernel", "graphics", "PdfFile"])
|
||||
mac_correct_rpath_library("OFDFile", ["UnicodeConverter", "kernel", "graphics", "PdfFile"])
|
||||
mac_correct_rpath_library("DocxRenderer", ["UnicodeConverter", "kernel", "graphics"])
|
||||
cmd("chmod", ["-v", "+x", "./x2t"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./x2t"], True)
|
||||
mac_correct_rpath_binary("./x2t", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "HtmlRenderer", "XpsFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "doctrenderer", "DocxRenderer"])
|
||||
mac_correct_rpath_library("IWorkFile", ["UnicodeConverter", "kernel"])
|
||||
mac_correct_rpath_library("HWPFile", ["UnicodeConverter", "kernel", "graphics"])
|
||||
|
||||
def correct_core_executable(name, libs):
|
||||
cmd("chmod", ["-v", "+x", name])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", name], True)
|
||||
mac_correct_rpath_binary(name, mac_icu_libs + libs)
|
||||
return
|
||||
|
||||
correct_core_executable("x2t", ["UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "doctrenderer", "DocxRenderer", "IWorkFile", "HWPFile"])
|
||||
if is_file("./allfontsgen"):
|
||||
cmd("chmod", ["-v", "+x", "./allfontsgen"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./allfontsgen"], True)
|
||||
mac_correct_rpath_binary("./allfontsgen", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "graphics"])
|
||||
correct_core_executable("allfontsgen", ["UnicodeConverter", "kernel", "graphics"])
|
||||
if is_file("./allthemesgen"):
|
||||
cmd("chmod", ["-v", "+x", "./allthemesgen"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./allthemesgen"], True)
|
||||
mac_correct_rpath_binary("./allthemesgen", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "graphics", "kernel_network", "doctrenderer"])
|
||||
correct_core_executable("allthemesgen", ["UnicodeConverter", "kernel", "graphics", "kernel_network", "doctrenderer", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "DocxRenderer"])
|
||||
if is_file("./pluginsmanager"):
|
||||
cmd("chmod", ["-v", "+x", "./pluginsmanager"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./pluginsmanager"], True)
|
||||
mac_correct_rpath_binary("./pluginsmanager", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "kernel_network"])
|
||||
correct_core_executable("pluginsmanager", ["UnicodeConverter", "kernel", "kernel_network"])
|
||||
if is_file("./vboxtester"):
|
||||
cmd("chmod", ["-v", "+x", "./vboxtester"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./vboxtester"], True)
|
||||
mac_correct_rpath_binary("./vboxtester", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "kernel_network"])
|
||||
correct_core_executable("vboxtester", ["UnicodeConverter", "kernel", "kernel_network"])
|
||||
if is_file("./x2ttester"):
|
||||
correct_core_executable("x2ttester", ["UnicodeConverter", "kernel", "graphics"])
|
||||
os.chdir(cur_dir)
|
||||
return
|
||||
|
||||
def mac_add_loader_path_to_rpath(libs):
|
||||
for lib in libs:
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
# icu libs are linked statically for frameworks
|
||||
if lib in mac_icu_libs:
|
||||
continue
|
||||
cmd("install_name_tool", ["-add_rpath", "@loader_path/../../..", lib + ".framework/" + lib], True)
|
||||
else:
|
||||
cmd("install_name_tool", ["-add_rpath", "@loader_path", "lib" + lib + ".dylib"], True)
|
||||
|
||||
def mac_correct_rpath_docbuilder(dir):
|
||||
cur_dir = os.getcwd()
|
||||
os.chdir(dir)
|
||||
cmd("chmod", ["-v", "+x", "./docbuilder"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path", "./docbuilder"], True)
|
||||
mac_correct_rpath_binary("./docbuilder", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "HtmlRenderer", "XpsFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "doctrenderer", "DocxRenderer"])
|
||||
mac_correct_rpath_library("docbuilder.c", ["icudata.58", "icuuc.58", "UnicodeConverter", "kernel", "kernel_network", "graphics", "doctrenderer"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@loader_path", "libdocbuilder.c.dylib"], True)
|
||||
mac_correct_rpath_binary("./docbuilder", mac_icu_libs + ["UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "IWorkFile", "HWPFile", "doctrenderer", "DocxRenderer"])
|
||||
mac_correct_rpath_library("docbuilder.c", mac_icu_libs + ["UnicodeConverter", "kernel", "kernel_network", "graphics", "doctrenderer", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "DocxRenderer"])
|
||||
|
||||
mac_add_loader_path_to_rpath(["icuuc." + icu_ver, "UnicodeConverter", "kernel", "kernel_network", "graphics", "doctrenderer", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "DocxRenderer", "docbuilder.c"])
|
||||
os.chdir(cur_dir)
|
||||
return
|
||||
|
||||
@ -1235,9 +1399,9 @@ def mac_correct_rpath_desktop(dir):
|
||||
os.chdir(dir)
|
||||
mac_correct_rpath_library("hunspell", [])
|
||||
mac_correct_rpath_library("ooxmlsignature", ["kernel"])
|
||||
mac_correct_rpath_library("ascdocumentscore", ["UnicodeConverter", "kernel", "graphics", "kernel_network", "PdfFile", "HtmlRenderer", "XpsFile", "DjVuFile", "hunspell", "ooxmlsignature"])
|
||||
cmd("install_name_tool", ["-change", "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework", "@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework", "libascdocumentscore.dylib"])
|
||||
mac_correct_rpath_binary("./editors_helper.app/Contents/MacOS/editors_helper", ["ascdocumentscore", "UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "HtmlRenderer", "XpsFile", "DjVuFile", "hunspell", "ooxmlsignature"])
|
||||
mac_correct_rpath_library("ascdocumentscore", ["UnicodeConverter", "kernel", "graphics", "kernel_network", "PdfFile", "XpsFile", "DjVuFile", "hunspell", "ooxmlsignature", "doctrenderer"])
|
||||
mac_change_rpath_library("ascdocumentscore", "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework", "@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework")
|
||||
mac_correct_rpath_binary("./editors_helper.app/Contents/MacOS/editors_helper", ["ascdocumentscore", "UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "hunspell", "ooxmlsignature", "doctrenderer"])
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path/../../../../Frameworks", "./editors_helper.app/Contents/MacOS/editors_helper"], True)
|
||||
cmd("install_name_tool", ["-add_rpath", "@executable_path/../../../../Resources/converter", "./editors_helper.app/Contents/MacOS/editors_helper"], True)
|
||||
cmd("chmod", ["-v", "+x", "./editors_helper.app/Contents/MacOS/editors_helper"])
|
||||
@ -1271,7 +1435,7 @@ def linux_set_origin_rpath_libraries(dir, libs):
|
||||
return
|
||||
|
||||
def linux_correct_rpath_docbuilder(dir):
|
||||
linux_set_origin_rpath_libraries(dir, ["docbuilder.c.so", "icuuc.so.58", "doctrenderer.so", "graphics.so", "kernel.so", "kernel_network.so", "UnicodeConverter.so"])
|
||||
linux_set_origin_rpath_libraries(dir, ["docbuilder.jni.so", "docbuilder.c.so", "icuuc.so." + icu_ver, "doctrenderer.so", "graphics.so", "kernel.so", "kernel_network.so", "UnicodeConverter.so", "PdfFile.so", "XpsFile.so", "OFDFile.so", "DjVuFile.so", "DocxRenderer.so"])
|
||||
return
|
||||
|
||||
def common_check_version(name, good_version, clean_func):
|
||||
@ -1327,7 +1491,7 @@ def copy_marketplace_plugin(dst_dir, is_name_as_guid=False, is_desktop_local=Fal
|
||||
git_dir = __file__script__path__ + "/../.."
|
||||
if False:
|
||||
# old version
|
||||
base.copy_sdkjs_plugin(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins", dst_dir, "manager", is_name_as_guid, is_desktop_local)
|
||||
copy_sdkjs_plugin(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins", dst_dir, "manager", is_name_as_guid, is_desktop_local)
|
||||
return
|
||||
src_dir_path = git_dir + "/onlyoffice.github.io/store/plugin"
|
||||
name = "marketplace"
|
||||
@ -1354,12 +1518,12 @@ def copy_sdkjs_plugins(dst_dir, is_name_as_guid=False, is_desktop_local=False, i
|
||||
plugins_dir = __file__script__path__ + "/../../onlyoffice.github.io/sdkjs-plugins/content"
|
||||
plugins_list_config = config.option("sdkjs-plugin")
|
||||
if isXp:
|
||||
plugins_list_config="photoeditor, macros, highlightcode, doc2md"
|
||||
plugins_list_config="photoeditor, highlightcode, doc2md"
|
||||
if ("" == plugins_list_config):
|
||||
return
|
||||
plugins_list = plugins_list_config.rsplit(", ")
|
||||
for name in plugins_list:
|
||||
copy_sdkjs_plugin(plugins_dir, dst_dir, name, is_name_as_guid, is_desktop_local)
|
||||
copy_sdkjs_plugin(plugins_dir, dst_dir, name, is_name_as_guid, is_desktop_local)
|
||||
return
|
||||
|
||||
def copy_sdkjs_plugins_server(dst_dir, is_name_as_guid=False, is_desktop_local=False):
|
||||
@ -1369,7 +1533,7 @@ def copy_sdkjs_plugins_server(dst_dir, is_name_as_guid=False, is_desktop_local=F
|
||||
return
|
||||
plugins_list = plugins_list_config.rsplit(", ")
|
||||
for name in plugins_list:
|
||||
copy_sdkjs_plugin(plugins_dir, dst_dir, name, is_name_as_guid, is_desktop_local)
|
||||
copy_sdkjs_plugin(plugins_dir, dst_dir, name, is_name_as_guid, is_desktop_local)
|
||||
return
|
||||
|
||||
def support_old_versions_plugins(out_dir):
|
||||
@ -1383,16 +1547,17 @@ def support_old_versions_plugins(out_dir):
|
||||
content_plugin_base += file.read()
|
||||
content_plugin_base += "\n\n"
|
||||
with open(get_path(out_dir + "/plugins-ui.js"), "r") as file:
|
||||
content_plugin_base += file.read()
|
||||
content_plugin_base += file.read()
|
||||
with open(get_path(out_dir + "/pluginBase.js"), "w") as file:
|
||||
file.write(content_plugin_base)
|
||||
delete_file(out_dir + "/plugins.js")
|
||||
delete_file(out_dir + "/plugins-ui.js")
|
||||
delete_file(out_dir + "/plugins-ui.js")
|
||||
return
|
||||
|
||||
def generate_sdkjs_plugin_list(dst):
|
||||
plugins_list = config.option("sdkjs-plugin").rsplit(", ") \
|
||||
+ config.option("sdkjs-plugin-server").rsplit(", ")
|
||||
plugins_list = list(filter(None, plugins_list))
|
||||
with open(get_path(dst), 'w') as file:
|
||||
dump = json.dumps(sorted(plugins_list), indent=4)
|
||||
file.write(re.sub(r"^(\s{4})", '\t', dump, 0, re.MULTILINE))
|
||||
@ -1419,7 +1584,7 @@ def hack_xcode_ios():
|
||||
filedata += "\n"
|
||||
filedata += content_hack
|
||||
filedata += "\n\n"
|
||||
|
||||
|
||||
delete_file(qmake_spec_file)
|
||||
with open(get_path(qmake_spec_file), "w") as file:
|
||||
file.write(filedata)
|
||||
@ -1500,12 +1665,12 @@ def copy_v8_files(core_dir, deploy_dir, platform, is_xp=False):
|
||||
if (-1 != config.option("config").find("use_javascript_core")):
|
||||
return
|
||||
directory_v8 = core_dir + "/Common/3dParty"
|
||||
|
||||
|
||||
if is_xp:
|
||||
directory_v8 += "/v8/v8_xp"
|
||||
copy_files(directory_v8 + platform + "/release/icudt*.dll", deploy_dir + "/")
|
||||
return
|
||||
|
||||
|
||||
if config.check_option("config", "v8_version_60"):
|
||||
directory_v8 += "/v8/v8/out.gn/"
|
||||
else:
|
||||
@ -1517,7 +1682,7 @@ def copy_v8_files(core_dir, deploy_dir, platform, is_xp=False):
|
||||
copy_files(directory_v8 + platform + "/icudt*.dat", deploy_dir + "/")
|
||||
return
|
||||
|
||||
def clone_marketplace_plugin(out_dir, is_name_as_guid=False, is_replace_paths=False, is_delete_git_dir=True, git_owner=""):
|
||||
def clone_marketplace_plugin(out_dir, is_name_as_guid=False, is_replace_paths=False, is_delete_git_dir=True, git_owner=""):
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(out_dir)
|
||||
git_update("onlyoffice.github.io", False, True, git_owner)
|
||||
@ -1538,11 +1703,11 @@ def clone_marketplace_plugin(out_dir, is_name_as_guid=False, is_replace_paths=Fa
|
||||
if is_dir(dst_dir_path):
|
||||
delete_dir(dst_dir_path)
|
||||
copy_dir(out_dir + "/onlyoffice.github.io/store/plugin", dst_dir_path)
|
||||
|
||||
|
||||
if is_replace_paths:
|
||||
for file in glob.glob(dst_dir_path + "/*.html"):
|
||||
replaceInFile(file, "https://onlyoffice.github.io/sdkjs-plugins/", "../")
|
||||
|
||||
|
||||
if is_delete_git_dir:
|
||||
delete_dir_with_access_error(out_dir + "/onlyoffice.github.io")
|
||||
return
|
||||
@ -1567,7 +1732,7 @@ def restorePathForBuilder(new_path):
|
||||
old_path = new_path[:-4]
|
||||
delete_file(old_path)
|
||||
copy_file(new_path, old_path)
|
||||
delete_file(new_path);
|
||||
delete_file(new_path)
|
||||
return
|
||||
|
||||
def generate_check_linux_system(build_tools_dir, out_dir):
|
||||
@ -1579,20 +1744,20 @@ def generate_check_linux_system(build_tools_dir, out_dir):
|
||||
def convert_ios_framework_to_xcframework(folder, lib):
|
||||
cur_dir = os.getcwd()
|
||||
os.chdir(folder)
|
||||
|
||||
|
||||
create_dir(lib + "_xc_tmp")
|
||||
create_dir(lib + "_xc_tmp/iphoneos")
|
||||
create_dir(lib + "_xc_tmp/iphonesimulator")
|
||||
copy_dir(lib + ".framework", lib + "_xc_tmp/iphoneos/" + lib + ".framework")
|
||||
copy_dir(lib + ".framework", lib + "_xc_tmp/iphonesimulator/" + lib + ".framework")
|
||||
|
||||
cmd("xcrun", ["lipo", "-remove", "x86_64", "./" + lib + "_xc_tmp/iphoneos/" + lib + ".framework/" + lib,
|
||||
cmd("xcrun", ["lipo", "-remove", "x86_64", "./" + lib + "_xc_tmp/iphoneos/" + lib + ".framework/" + lib,
|
||||
"-o", "./" + lib + "_xc_tmp/iphoneos/" + lib + ".framework/" + lib])
|
||||
cmd("xcrun", ["lipo", "-remove", "arm64", "./" + lib + "_xc_tmp/iphonesimulator/" + lib + ".framework/" + lib,
|
||||
cmd("xcrun", ["lipo", "-remove", "arm64", "./" + lib + "_xc_tmp/iphonesimulator/" + lib + ".framework/" + lib,
|
||||
"-o", "./" + lib + "_xc_tmp/iphonesimulator/" + lib + ".framework/" + lib])
|
||||
|
||||
cmd("xcodebuild", ["-create-xcframework",
|
||||
"-framework", "./" + lib + "_xc_tmp/iphoneos/" + lib + ".framework/",
|
||||
cmd("xcodebuild", ["-create-xcframework",
|
||||
"-framework", "./" + lib + "_xc_tmp/iphoneos/" + lib + ".framework/",
|
||||
"-framework", "./" + lib + "_xc_tmp/iphonesimulator/" + lib + ".framework/",
|
||||
"-output", lib + ".xcframework"])
|
||||
|
||||
@ -1608,7 +1773,7 @@ def convert_ios_framework_to_xcframework_folder(folder, libs):
|
||||
|
||||
def change_elf_rpath(path, origin):
|
||||
# excludes ---
|
||||
if (-1 != path.find("libicudata.so.58")):
|
||||
if (-1 != path.find("libicudata.so." + icu_ver)):
|
||||
return
|
||||
# ------------
|
||||
tools_dir = get_script_dir() + "/../tools/linux/elf/"
|
||||
@ -1640,7 +1805,7 @@ def change_elf_rpath(path, origin):
|
||||
cmd(tools_dir + "patchelf", ["--set-rpath", new_path, path], True)
|
||||
#print("[" + os.path.basename(path) + "] old: " + old_path + "; new: " + new_path)
|
||||
return
|
||||
|
||||
|
||||
def correct_elf_rpath_directory(directory, origin, is_recursion = True):
|
||||
for file in glob.glob(directory + "/*"):
|
||||
if is_file(file):
|
||||
@ -1693,14 +1858,14 @@ def copy_dictionaries(src, dst, is_hyphen = True, is_spell = True):
|
||||
|
||||
if is_hyphen and is_hyphen_present:
|
||||
copy_dir_content(file, lang_folder, "hyph_", "")
|
||||
|
||||
|
||||
if is_spell and is_spell_present:
|
||||
copy_dir_content(file, lang_folder, "", "hyph_")
|
||||
|
||||
if is_file(dst + "/en_US/en_US_thes.dat"):
|
||||
delete_file(dst + "/en_US/en_US_thes.dat")
|
||||
delete_file(dst + "/en_US/en_US_thes.idx")
|
||||
|
||||
|
||||
if is_file(dst + "/ru_RU/ru_RU_oo3.dic"):
|
||||
delete_file(dst + "/ru_RU/ru_RU_oo3.dic")
|
||||
delete_file(dst + "/ru_RU/ru_RU_oo3.aff")
|
||||
@ -1722,6 +1887,23 @@ def check_module_version(actual_version, clear_func):
|
||||
clear_func()
|
||||
return
|
||||
|
||||
|
||||
def set_sysroot_env():
|
||||
global ENV_BEFORE_SYSROOT
|
||||
ENV_BEFORE_SYSROOT = dict(os.environ)
|
||||
if "linux" == host_platform() and config.option("sysroot") != "":
|
||||
os.environ['PATH'] = config.option("sysroot") + "/usr/bin:" + get_env("PATH")
|
||||
os.environ['LD_LIBRARY_PATH'] = config.get_custom_sysroot_lib()
|
||||
os.environ['CC'] = config.get_custom_sysroot_bin() + "/gcc"
|
||||
os.environ['CXX'] = config.get_custom_sysroot_bin() + "/g++"
|
||||
os.environ['CFLAGS'] = "--sysroot=" + config.option("sysroot")
|
||||
os.environ['CXXFLAGS'] = "--sysroot=" + config.option("sysroot")
|
||||
check_python()
|
||||
|
||||
def restore_sysroot_env():
|
||||
os.environ.clear()
|
||||
os.environ.update(ENV_BEFORE_SYSROOT)
|
||||
|
||||
def check_python():
|
||||
if ("linux" != host_platform()):
|
||||
return
|
||||
@ -1729,6 +1911,7 @@ def check_python():
|
||||
directory_bin = __file__script__path__ + "/../tools/linux/python3/bin"
|
||||
|
||||
if not is_dir(directory + "/python3"):
|
||||
download('https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/python3.tar.gz', directory + "/python3.tar.gz")
|
||||
cmd("tar", ["xfz", directory + "/python3.tar.gz", "-C", directory])
|
||||
cmd("ln", ["-s", directory_bin + "/python3", directory_bin + "/python"])
|
||||
directory_bin = directory_bin.replace(" ", "\\ ")
|
||||
@ -1754,3 +1937,114 @@ def apply_patch(file, patch):
|
||||
#file_content_new = "\n#if 0" + file_content_old + "#else" + file_content_new + "#endif\n"
|
||||
replaceInFile(file, file_content_old, file_content_new)
|
||||
return
|
||||
|
||||
def get_autobuild_version(product, platform="", branch="", build=""):
|
||||
download_platform = platform
|
||||
if ("" == download_platform):
|
||||
osType = get_platform()
|
||||
is64 = True if (osType.endswith("64")) else False
|
||||
isArm = False
|
||||
if (-1 != osType.find("arm")) or (-1 != osType.find("aarch64")):
|
||||
isArm = True
|
||||
|
||||
if ("windows" == host_platform()):
|
||||
download_platform = "win-"
|
||||
elif ("linux" == host_platform()):
|
||||
download_platform = "linux-"
|
||||
else:
|
||||
download_platform = "mac-"
|
||||
|
||||
download_platform += ("arm" if isArm else "")
|
||||
download_platform += ("64" if is64 else "32")
|
||||
else:
|
||||
download_platform = download_platform.replace("_", "-")
|
||||
|
||||
download_build = build
|
||||
if ("" == download_build):
|
||||
download_build = "latest"
|
||||
|
||||
download_branch = branch
|
||||
if ("" == download_branch):
|
||||
download_branch = "develop"
|
||||
|
||||
download_addon = download_branch + "/" + download_build + "/" + product + "-" + download_platform + ".7z"
|
||||
return "http://repo-doc-onlyoffice-com.s3.amazonaws.com/archive/" + download_addon
|
||||
|
||||
def is_use_create_artifacts_qemu_any_platform():
|
||||
if config.check_option("platform", "win_arm64") and not is_os_arm():
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_use_create_artifacts_qemu(platform):
|
||||
if platform == "win_arm64" and not is_os_arm():
|
||||
return True
|
||||
return False
|
||||
|
||||
def create_artifacts_qemu_any_platform():
|
||||
if not is_use_create_artifacts_qemu_any_platform():
|
||||
return
|
||||
if config.check_option("platform", "win_arm64"):
|
||||
create_artifacts_qemu_win_arm()
|
||||
return;
|
||||
|
||||
def create_artifacts_qemu_win_arm():
|
||||
if config.option("qemu-win-arm64-dir") == "":
|
||||
print("For deploying win_arm64 on non arm host you should provide qemu-win-arm64-dir. More info in tools/win/qemu/README.md")
|
||||
return
|
||||
|
||||
old_curr_dir = os.path.abspath(os.curdir)
|
||||
qemu_dir = os.path.abspath(config.option("qemu-win-arm64-dir"))
|
||||
|
||||
os.chdir(qemu_dir)
|
||||
start_qemu_bat_path = f"start.bat"
|
||||
cmd(start_qemu_bat_path, [])
|
||||
os.chdir(old_curr_dir)
|
||||
|
||||
def create_x2t_js_cache(dir, product, platform):
|
||||
# mac
|
||||
if is_file(dir + "/libdoctrenderer.dylib") or is_dir(dir + "/doctrenderer.framework"):
|
||||
doctrenderer_lib = "libdoctrenderer.dylib" if is_file(dir + "/libdoctrenderer.dylib") else "doctrenderer.framework/doctrenderer"
|
||||
if os.path.getsize(dir + "/" + doctrenderer_lib) < 5*1024*1024:
|
||||
return
|
||||
|
||||
if ((platform == "linux_arm64") and not is_os_arm()):
|
||||
cmd_in_dir_qemu(platform, dir, "./x2t", ["-create-js-snapshots"], True)
|
||||
return
|
||||
|
||||
cmd_in_dir(dir, "./x2t", ["-create-js-snapshots"], True)
|
||||
return
|
||||
|
||||
def setup_local_qmake(dir_qmake):
|
||||
dir_base = os.path.dirname(dir_qmake)
|
||||
writeFile(dir_base + "/onlyoffice_qt.conf", "Prefix = " + dir_base)
|
||||
return
|
||||
|
||||
def deploy_icu(core_dir, dst_dir, platform):
|
||||
if (0 == platform.find("android")):
|
||||
src_dir = core_dir + "/Common/3dParty/icu/android/build/" + platform[8:]
|
||||
copy_file(src_dir + "/icudt" + icu_ver + "l.dat", dst_dir + "/icudt" + icu_ver + "l.dat")
|
||||
return
|
||||
|
||||
isXp = False
|
||||
if platform.endswith("xp"):
|
||||
isXp = True
|
||||
platform = platform[0:-3]
|
||||
src_dir = core_dir + "/Common/3dParty/icu/" + platform + "/build"
|
||||
|
||||
if (0 == platform.find("win")):
|
||||
icu_ver_win = icu_ver
|
||||
if isXp:
|
||||
icu_ver_win = icu_ver_old
|
||||
src_dir += "/xp"
|
||||
copy_file(src_dir + "/icudt" + icu_ver_win + ".dll", dst_dir + "/icudt" + icu_ver_win + ".dll")
|
||||
copy_file(src_dir + "/icuuc" + icu_ver_win + ".dll", dst_dir + "/icuuc" + icu_ver_win + ".dll")
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
copy_file(src_dir + "/libicudata.so." + icu_ver, dst_dir + "/libicudata.so." + icu_ver)
|
||||
copy_file(src_dir + "/libicuuc.so." + icu_ver, dst_dir + "/libicuuc.so." + icu_ver)
|
||||
|
||||
if (0 == platform.find("mac") and not config.check_option("config", "bundle_dylibs")):
|
||||
copy_file(src_dir + "/libicudata." + icu_ver + ".dylib", dst_dir + "/libicudata." + icu_ver + ".dylib")
|
||||
copy_file(src_dir + "/libicuuc." + icu_ver + ".dylib", dst_dir + "/libicuuc." + icu_ver + ".dylib")
|
||||
|
||||
return
|
||||
|
||||
@ -33,34 +33,38 @@ def make():
|
||||
base.set_env('NODE_ENV', 'production')
|
||||
|
||||
base_dir = base.get_script_dir() + "/.."
|
||||
out_dir = base_dir + "/out/js/";
|
||||
out_dir = base_dir + "/out/js/"
|
||||
branding = config.option("branding-name")
|
||||
if ("" == branding):
|
||||
branding = "onlyoffice"
|
||||
out_dir += branding
|
||||
base.create_dir(out_dir)
|
||||
|
||||
isOnlyMobile = False
|
||||
if (config.option("module") == "mobile"):
|
||||
isOnlyMobile = True
|
||||
|
||||
# builder
|
||||
build_interface(base_dir + "/../web-apps/build")
|
||||
build_sdk_builder(base_dir + "/../sdkjs/build")
|
||||
base.create_dir(out_dir + "/builder")
|
||||
base.copy_dir(base_dir + "/../web-apps/deploy/web-apps", out_dir + "/builder/web-apps")
|
||||
base.copy_dir(base_dir + "/../sdkjs/deploy/sdkjs", out_dir + "/builder/sdkjs")
|
||||
correct_sdkjs_licence(out_dir + "/builder/sdkjs")
|
||||
if not isOnlyMobile:
|
||||
base.cmd_in_dir(base_dir + "/../web-apps/translation", "python", ["merge_and_check.py"])
|
||||
build_interface(base_dir + "/../web-apps/build")
|
||||
build_sdk_builder(base_dir + "/../sdkjs/build")
|
||||
base.create_dir(out_dir + "/builder")
|
||||
base.copy_dir(base_dir + "/../web-apps/deploy/web-apps", out_dir + "/builder/web-apps")
|
||||
base.copy_dir(base_dir + "/../sdkjs/deploy/sdkjs", out_dir + "/builder/sdkjs")
|
||||
correct_sdkjs_licence(out_dir + "/builder/sdkjs")
|
||||
|
||||
# desktop
|
||||
if config.check_option("module", "desktop"):
|
||||
if config.check_option("module", "desktop") and not isOnlyMobile:
|
||||
build_sdk_desktop(base_dir + "/../sdkjs/build")
|
||||
base.create_dir(out_dir + "/desktop")
|
||||
base.copy_dir(base_dir + "/../sdkjs/deploy/sdkjs", out_dir + "/desktop/sdkjs")
|
||||
correct_sdkjs_licence(out_dir + "/desktop/sdkjs")
|
||||
base.copy_dir(base_dir + "/../web-apps/deploy/web-apps", out_dir + "/desktop/web-apps")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/documenteditor/embed")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/documenteditor/mobile")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/presentationeditor/embed")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/presentationeditor/mobile")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/spreadsheeteditor/embed")
|
||||
base.delete_dir(out_dir + "/desktop/web-apps/apps/spreadsheeteditor/mobile")
|
||||
|
||||
deldirs = ['ie', 'mobile', 'embed']
|
||||
[base.delete_dir(root + "/" + d) for root, dirs, f in os.walk(out_dir + "/desktop/web-apps/apps") for d in dirs if d in deldirs]
|
||||
|
||||
base.copy_file(base_dir + "/../web-apps/apps/api/documents/index.html.desktop", out_dir + "/desktop/web-apps/apps/api/documents/index.html")
|
||||
|
||||
build_interface(base_dir + "/../desktop-apps/common/loginpage/build")
|
||||
@ -69,7 +73,7 @@ def make():
|
||||
|
||||
# mobile
|
||||
if config.check_option("module", "mobile"):
|
||||
build_sdk_native(base_dir + "/../sdkjs/build", False)
|
||||
build_sdk_native(base_dir + "/../sdkjs/build")
|
||||
base.create_dir(out_dir + "/mobile")
|
||||
base.create_dir(out_dir + "/mobile/sdkjs")
|
||||
vendor_dir_src = base_dir + "/../web-apps/vendor/"
|
||||
@ -101,7 +105,10 @@ def make():
|
||||
|
||||
# JS build
|
||||
def _run_npm(directory):
|
||||
return base.cmd_in_dir(directory, "npm", ["install"])
|
||||
retValue = base.cmd_in_dir(directory, "npm", ["install"], True)
|
||||
if (0 != retValue):
|
||||
retValue = base.cmd_in_dir(directory, "npm", ["install", "--verbose"])
|
||||
return retValue
|
||||
|
||||
def _run_npm_ci(directory):
|
||||
return base.cmd_in_dir(directory, "npm", ["ci"])
|
||||
@ -114,7 +121,7 @@ def _run_grunt(directory, params=[]):
|
||||
|
||||
def build_interface(directory):
|
||||
_run_npm(directory)
|
||||
_run_grunt(directory, ["--force"] + base.web_apps_addons_param())
|
||||
_run_grunt(directory, ["--force", "--verbose"] + base.web_apps_addons_param())
|
||||
return
|
||||
|
||||
def get_build_param(minimize=True):
|
||||
@ -168,6 +175,7 @@ def build_js_develop(root_dir):
|
||||
_run_npm(root_dir + external_folder + "/web-apps/build")
|
||||
_run_npm_ci(root_dir + external_folder + "/web-apps/build/sprites")
|
||||
_run_grunt(root_dir + external_folder + "/web-apps/build/sprites", [])
|
||||
base.cmd_in_dir(root_dir + external_folder + "/web-apps/translation", "python", ["merge_and_check.py"])
|
||||
|
||||
old_cur = os.getcwd()
|
||||
old_product_version = base.get_env("PRODUCT_VERSION")
|
||||
|
||||
@ -38,7 +38,8 @@ def make():
|
||||
if(base.is_exist(custom_public_key)):
|
||||
base.copy_file(custom_public_key, server_dir + '/Common/sources')
|
||||
|
||||
pkg_target = "node16"
|
||||
#node22 packaging has issue https://github.com/yao-pkg/pkg/issues/87
|
||||
pkg_target = "node20"
|
||||
|
||||
if ("linux" == base.host_platform()):
|
||||
pkg_target += "-linux"
|
||||
@ -51,6 +52,7 @@ def make():
|
||||
base.cmd_in_dir(server_dir + "/DocService", "pkg", [".", "-t", pkg_target, "--options", "max_old_space_size=4096", "-o", "docservice"])
|
||||
base.cmd_in_dir(server_dir + "/FileConverter", "pkg", [".", "-t", pkg_target, "-o", "converter"])
|
||||
base.cmd_in_dir(server_dir + "/Metrics", "pkg", [".", "-t", pkg_target, "-o", "metrics"])
|
||||
base.cmd_in_dir(server_dir + "/AdminPanel/server", "pkg", [".", "-t", pkg_target, "-o", "adminpanel"])
|
||||
|
||||
example_dir = base.get_script_dir() + "/../../document-server-integration/web/documentserver-example/nodejs"
|
||||
base.delete_dir(example_dir + "/node_modules")
|
||||
@ -64,10 +66,9 @@ def build_server_with_addons():
|
||||
for addon in addons:
|
||||
if (addon):
|
||||
addon_dir = base.get_script_dir() + "/../../" + addon
|
||||
base.cmd_in_dir(addon_dir, "npm", ["ci"])
|
||||
base.cmd_in_dir(addon_dir, "npm", ["run", "build"])
|
||||
if (base.is_exist(addon_dir)):
|
||||
base.cmd_in_dir(addon_dir, "npm", ["ci"])
|
||||
base.cmd_in_dir(addon_dir, "npm", ["run", "build"])
|
||||
|
||||
def build_server_develop():
|
||||
server_dir = base.get_script_dir() + "/../../server"
|
||||
base.cmd_in_dir(server_dir, "npm", ["ci"])
|
||||
base.cmd_in_dir(server_dir, "grunt", ["develop", "-v"] + base.server_addons_param())
|
||||
build_server_with_addons()
|
||||
|
||||
@ -35,15 +35,41 @@ def make(solution=""):
|
||||
qmake.make(platform, pro, "xcframework_platform_ios_simulator")
|
||||
|
||||
if config.check_option("module", "builder") and base.is_windows() and "onlyoffice" == config.branding():
|
||||
# check branding libs
|
||||
if (config.option("branding-name") == "onlyoffice"):
|
||||
for platform in platforms:
|
||||
if not platform in config.platforms:
|
||||
continue
|
||||
core_lib_unbranding_dir = os.getcwd() + "/../core/build/lib/" + platform + base.qt_dst_postfix()
|
||||
if not base.is_dir(core_lib_unbranding_dir):
|
||||
base.create_dir(core_lib_unbranding_dir)
|
||||
core_lib_branding_dir = os.getcwd() + "/../core/build/onlyoffice/lib/" + platform + base.qt_dst_postfix()
|
||||
base.copy_file(core_lib_branding_dir + "/doctrenderer.dll", core_lib_unbranding_dir + "/doctrenderer.dll")
|
||||
base.copy_file(core_lib_branding_dir + "/doctrenderer.lib", core_lib_unbranding_dir + "/doctrenderer.lib")
|
||||
|
||||
# check replace
|
||||
new_replace_path = base.correctPathForBuilder(os.getcwd() + "/../core/DesktopEditor/doctrenderer/docbuilder.com/src/docbuilder.h")
|
||||
if ("2019" == config.option("vs-version")):
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.com/src", "docbuilder.com_2019.sln")
|
||||
if (True):
|
||||
new_path_net = base.correctPathForBuilder(os.getcwd() + "/../core/DesktopEditor/doctrenderer/docbuilder.net/src/docbuilder.net.cpp")
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.net/src", "docbuilder.net.sln")
|
||||
base.restorePathForBuilder(new_path_net)
|
||||
else:
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.com/src", "docbuilder.com.sln")
|
||||
base.restorePathForBuilder(new_replace_path)
|
||||
directory_builder_branding = os.getcwd() + "/../core/DesktopEditor/doctrenderer"
|
||||
if base.is_dir(directory_builder_branding):
|
||||
new_replace_path = base.correctPathForBuilder(directory_builder_branding + "/docbuilder.com/src/docbuilder.h")
|
||||
if ("2019" == config.option("vs-version")):
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.com/src", "docbuilder.com_2019.sln")
|
||||
if (True):
|
||||
new_path_net = base.correctPathForBuilder(directory_builder_branding + "/docbuilder.net/src/docbuilder.net.cpp")
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.net/src", "docbuilder.net.sln")
|
||||
base.restorePathForBuilder(new_path_net)
|
||||
else:
|
||||
base.make_sln_project("../core/DesktopEditor/doctrenderer/docbuilder.com/src", "docbuilder.com.sln")
|
||||
base.restorePathForBuilder(new_replace_path)
|
||||
|
||||
# build Java docbuilder wrapper
|
||||
if config.check_option("module", "builder") and "onlyoffice" == config.branding():
|
||||
for platform in platforms:
|
||||
if not platform in config.platforms:
|
||||
continue
|
||||
|
||||
# build JNI library
|
||||
qmake.make(platform, base.get_script_dir() + "/../../core/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_jni.pro", "", True)
|
||||
# build Java code to JAR
|
||||
base.cmd_in_dir(base.get_script_dir() + "/../../core/DesktopEditor/doctrenderer/docbuilder.java", "python", ["make.py"])
|
||||
|
||||
return
|
||||
|
||||
@ -24,7 +24,7 @@ def parse():
|
||||
|
||||
# all platforms
|
||||
global platforms
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp",
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp", "win_arm64",
|
||||
"linux_64", "linux_32", "linux_arm64",
|
||||
"mac_64", "mac_arm64",
|
||||
"ios",
|
||||
@ -57,6 +57,12 @@ def parse():
|
||||
if not check_option("platform", "mac_64"):
|
||||
options["platform"] = "mac_64 " + options["platform"]
|
||||
|
||||
if (False):
|
||||
# use qemu on deploy for emulation
|
||||
if ("windows" == host_platform) and check_option("platform", "win_arm64") and not base.is_os_arm():
|
||||
if not check_option("platform", "win_64"):
|
||||
options["platform"] = "win_64 " + options["platform"]
|
||||
|
||||
if ("linux" == host_platform) and check_option("platform", "linux_arm64") and not base.is_os_arm():
|
||||
if not check_option("platform", "linux_64"):
|
||||
# linux_64 binaries need only for desktop
|
||||
@ -77,6 +83,27 @@ def parse():
|
||||
|
||||
if ("windows" == host_platform) and ("2019" == option("vs-version")):
|
||||
extend_option("config", "vs2019")
|
||||
|
||||
# sysroot setup
|
||||
if "linux" != host_platform and "sysroot" in options:
|
||||
options["sysroot"] = ""
|
||||
|
||||
if "linux" == host_platform and "sysroot" in options:
|
||||
if options["sysroot"] == "0":
|
||||
options["sysroot"] = ""
|
||||
elif options["sysroot"] == "1":
|
||||
dst_dir = os.path.abspath(base.get_script_dir(__file__) + '/../tools/linux/sysroot')
|
||||
custom_sysroot = dst_dir + '/sysroot_ubuntu_1604'
|
||||
options["sysroot"] = custom_sysroot
|
||||
if not os.path.isdir(custom_sysroot):
|
||||
print("Sysroot is not found, downloading...")
|
||||
sysroot_url = 'https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/sysroot/sysroot_ubuntu_1604.tar.xz'
|
||||
base.download(sysroot_url, dst_dir + '/sysroot_ubuntu_1604.tar.xz')
|
||||
os.mkdir(custom_sysroot)
|
||||
print("Unpacking...")
|
||||
base.cmd2('tar', ['-xf', dst_dir + '/sysroot_ubuntu_1604.tar.xz', '-C', dst_dir])
|
||||
if os.path.exists(dst_dir + '/sysroot_ubuntu_1604.tar.xz'):
|
||||
os.remove(dst_dir + '/sysroot_ubuntu_1604.tar.xz')
|
||||
|
||||
if is_cef_107():
|
||||
extend_option("config", "cef_version_107")
|
||||
@ -105,7 +132,10 @@ def parse():
|
||||
options["sdkjs-plugin-server"] = "default"
|
||||
|
||||
if not "arm64-toolchain-bin" in options:
|
||||
options["arm64-toolchain-bin"] = "/usr/bin"
|
||||
if not "sysroot" in options:
|
||||
options["arm64-toolchain-bin"] = "/usr/bin"
|
||||
else:
|
||||
options["arm64-toolchain-bin"] = get_custom_sysroot_bin()
|
||||
|
||||
if check_option("platform", "ios"):
|
||||
if not check_option("config", "no_bundle_xcframeworks"):
|
||||
@ -116,6 +146,10 @@ def parse():
|
||||
if not check_option("config", "bundle_dylibs"):
|
||||
extend_option("config", "bundle_dylibs")
|
||||
|
||||
if ("mac" == host_platform) and check_option("module", "desktop"):
|
||||
if not check_option("config", "bundle_dylibs"):
|
||||
extend_option("config", "bundle_dylibs")
|
||||
|
||||
if check_option("use-system-qt", "1"):
|
||||
base.cmd_in_dir(base.get_script_dir() + "/../tools/linux", "python", ["use_system_qt.py"])
|
||||
options["qt-dir"] = base.get_script_dir() + "/../tools/linux/system_qt"
|
||||
@ -139,6 +173,9 @@ def check_compiler(platform):
|
||||
if (0 == platform.find("win")):
|
||||
compiler["compiler"] = "msvc" + options["vs-version"]
|
||||
compiler["compiler_64"] = "msvc" + options["vs-version"] + "_64"
|
||||
if (0 == platform.find("win_arm")):
|
||||
compiler["compiler"] = "msvc" + options["vs-version"] + "_arm"
|
||||
compiler["compiler_64"] = "msvc" + options["vs-version"] + "_arm64"
|
||||
elif (0 == platform.find("linux")):
|
||||
compiler["compiler"] = "gcc"
|
||||
compiler["compiler_64"] = "gcc_64"
|
||||
@ -199,6 +236,14 @@ def is_mobile_platform():
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_custom_sysroot_bin():
|
||||
return option("sysroot") + "/usr/bin"
|
||||
|
||||
# todo 32bit support?
|
||||
def get_custom_sysroot_lib():
|
||||
if base.is_os_64bit():
|
||||
return option("sysroot") + "/usr/lib/x86_64-linux-gnu"
|
||||
|
||||
def parse_defaults():
|
||||
defaults_path = base.get_script_dir() + "/../defaults"
|
||||
if ("" != option("branding")):
|
||||
|
||||
@ -16,12 +16,16 @@ import curl
|
||||
import websocket_all
|
||||
import v8
|
||||
import html2
|
||||
import iwork
|
||||
import md
|
||||
import hunspell
|
||||
import glew
|
||||
import harfbuzz
|
||||
import oo_brotli
|
||||
import hyphen
|
||||
import googletest
|
||||
import libvlc
|
||||
import heif
|
||||
|
||||
def check_android_ndk_macos_arm(dir):
|
||||
if base.is_dir(dir + "/darwin-x86_64") and not base.is_dir(dir + "/darwin-arm64"):
|
||||
@ -42,15 +46,19 @@ def make():
|
||||
openssl.make()
|
||||
v8.make()
|
||||
html2.make()
|
||||
iwork.make(False)
|
||||
md.make()
|
||||
hunspell.make(False)
|
||||
harfbuzz.make()
|
||||
glew.make()
|
||||
hyphen.make()
|
||||
googletest.make()
|
||||
oo_brotli.make()
|
||||
heif.make()
|
||||
|
||||
if config.check_option("build-libvlc", "1"):
|
||||
libvlc.make()
|
||||
|
||||
|
||||
if config.check_option("module", "mobile"):
|
||||
if (config.check_option("platform", "android")):
|
||||
curl.make()
|
||||
|
||||
@ -71,13 +71,6 @@ else:
|
||||
"arch" : "darwin-x86_64"
|
||||
}
|
||||
|
||||
def get_android_ndk_version():
|
||||
#return "26.2.11394342"
|
||||
return "21.1.6352462"
|
||||
|
||||
def get_android_ndk_version_major():
|
||||
return int(get_android_ndk_version().split(".")[0])
|
||||
|
||||
def get_options_dict_as_array(opts):
|
||||
value = []
|
||||
for key in opts:
|
||||
|
||||
@ -11,8 +11,8 @@ current_dir = os.path.abspath(current_dir)
|
||||
if not current_dir.endswith("/"):
|
||||
current_dir += "/"
|
||||
|
||||
icu_major = "58"
|
||||
icu_minor = "3"
|
||||
icu_major = "74"
|
||||
icu_minor = "2"
|
||||
|
||||
options = {
|
||||
"--enable-strict" : "no",
|
||||
@ -41,12 +41,12 @@ cpp_flags_base = [
|
||||
cpp_flags = [
|
||||
"-fno-short-wchar",
|
||||
"-fno-short-enums",
|
||||
|
||||
|
||||
"-DU_USING_ICU_NAMESPACE=0",
|
||||
"-DU_HAVE_NL_LANGINFO_CODESET=0",
|
||||
"-DU_TIMEZONE=0",
|
||||
"-DU_DISABLE_RENAMING=0",
|
||||
|
||||
|
||||
"-DUCONFIG_NO_COLLATION=0",
|
||||
"-DUCONFIG_NO_FORMATTING=0",
|
||||
"-DUCONFIG_NO_REGULAR_EXPRESSIONS=0",
|
||||
@ -55,16 +55,11 @@ cpp_flags = [
|
||||
"-DU_STATIC_IMPLEMENTATION"
|
||||
]
|
||||
|
||||
def fetch_icu():
|
||||
def fetch_icu(major, minor):
|
||||
if not base.is_dir(current_dir + "icu"):
|
||||
base.cmd("git", ["clone", "--depth", "1", "--branch", "maint/maint-" + icu_major, "https://github.com/unicode-org/icu.git", current_dir + "icu2"])
|
||||
base.cmd("git", ["clone", "--depth", "1", "--branch", "release-" + major + "-" + minor, "https://github.com/unicode-org/icu.git", current_dir + "icu2"])
|
||||
base.copy_dir(current_dir + "icu2/icu4c", current_dir + "icu")
|
||||
base.delete_dir_with_access_error(current_dir + "icu2")
|
||||
|
||||
if ("linux" == base.host_platform()):
|
||||
base.replaceInFile(current_dir + "/icu/source/i18n/digitlst.cpp", "xlocale", "locale")
|
||||
if False and ("mac" == base.host_platform()):
|
||||
base.replaceInFile(current_dir + "/icu/source/tools/pkgdata/pkgdata.cpp", "cmd, \"%s %s -o %s%s %s %s%s %s %s\",", "cmd, \"%s %s -o %s%s %s %s %s %s %s\",")
|
||||
return
|
||||
|
||||
def build_host():
|
||||
@ -111,9 +106,9 @@ def build_arch(arch):
|
||||
cross_build_dir = os.path.abspath(current_dir + "icu/cross_build")
|
||||
arch_build_dir = os.path.abspath(current_dir + "build/tmp")
|
||||
base.create_dir(arch_build_dir)
|
||||
|
||||
|
||||
os.chdir(arch_build_dir)
|
||||
base.cmd("./../../icu/source/configure", ["--with-cross-build=" + cross_build_dir] +
|
||||
base.cmd("./../../icu/source/configure", ["--with-cross-build=" + cross_build_dir] +
|
||||
android_ndk.get_options_dict_as_array(options) + ["--host=" + android_ndk.platforms[arch]["target"], "--prefix=" + arch_build_dir])
|
||||
base.cmd("make", ["-j4"])
|
||||
os.chdir(current_dir)
|
||||
@ -132,7 +127,7 @@ def make():
|
||||
|
||||
old_env = dict(os.environ)
|
||||
|
||||
fetch_icu()
|
||||
fetch_icu(icu_major, icu_minor)
|
||||
|
||||
build_host()
|
||||
|
||||
|
||||
@ -22,10 +22,10 @@ def move_debug_libs_windows(dir):
|
||||
|
||||
def clean():
|
||||
if base.is_dir("boost_1_58_0"):
|
||||
base.delete_dir_with_access_error("boost_1_58_0");
|
||||
base.delete_dir_with_access_error("boost_1_58_0")
|
||||
base.delete_dir("boost_1_58_0")
|
||||
if base.is_dir("boost_1_72_0"):
|
||||
base.delete_dir_with_access_error("boost_1_72_0");
|
||||
base.delete_dir_with_access_error("boost_1_72_0")
|
||||
base.delete_dir("boost_1_72_0")
|
||||
if base.is_dir("build"):
|
||||
base.delete_dir("build")
|
||||
@ -85,14 +85,36 @@ def make():
|
||||
base.cmd("b2.exe", ["headers"])
|
||||
base.cmd("b2.exe", ["--clean"])
|
||||
base.cmd("b2.exe", ["--prefix=./../build/win_32", "link=static", "--with-filesystem", "--with-system", "--with-date_time", "--with-regex", "--toolset=" + win_toolset, "address-model=32", "install"])
|
||||
if (-1 != config.option("platform").find("win_arm64") and not base.is_file("../build/win_arm64/lib/libboost_system-" + win_vs_version + "-mt-a64-1_72.lib")):
|
||||
boost_bat = []
|
||||
boost_bat.append("call bootstrap.bat " + win_boot_arg) # first build b2 for win64, so vcvarsall_call with arm64 later
|
||||
vcvarsall_call = ("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + "x64_arm64")
|
||||
boost_bat.append(vcvarsall_call)
|
||||
boost_bat.append("call b2.exe headers")
|
||||
boost_bat.append("call b2.exe --clean")
|
||||
boost_bat.append("call b2.exe --prefix=./../build/win_arm64 architecture=arm link=static --with-filesystem --with-system --with-date_time --with-regex --toolset=" + win_toolset + " address-model=64 install")
|
||||
base.run_as_bat(boost_bat)
|
||||
correct_install_includes_win(base_dir, "win_64")
|
||||
correct_install_includes_win(base_dir, "win_32")
|
||||
correct_install_includes_win(base_dir, "win_32")
|
||||
correct_install_includes_win(base_dir, "win_arm64")
|
||||
|
||||
if config.check_option("platform", "linux_64") and not base.is_dir("../build/linux_64"):
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=filesystem,system,date_time,regex"])
|
||||
base.cmd("./b2", ["headers"])
|
||||
base.cmd("./b2", ["--clean"])
|
||||
base.cmd("./b2", ["--prefix=./../build/linux_64", "link=static", "cxxflags=-fPIC", "install"])
|
||||
if config.option("sysroot") == "":
|
||||
addon_config = []
|
||||
addon_compile = []
|
||||
if "1" == config.option("use-clang"):
|
||||
addon_config = ["--with-toolset=clang"]
|
||||
addon_compile = ["cxxflags=-stdlib=libc++", "linkflags=-stdlib=libc++", "define=_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"]
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=filesystem,system,date_time,regex"] + addon_config)
|
||||
base.cmd("./b2", ["headers"])
|
||||
base.cmd("./b2", ["--clean"])
|
||||
base.cmd("./b2", ["--prefix=./../build/linux_64", "link=static", "cxxflags=-fPIC"] + addon_compile + ["install"])
|
||||
else: # build via qmake when custom sysroot is needed
|
||||
boost_qt.make(os.getcwd(), ["filesystem", "system", "date_time", "regex"], "linux_64")
|
||||
directory_build = base_dir + "/build/linux_64/lib"
|
||||
base.delete_file(directory_build + "/libboost_system.a")
|
||||
base.delete_file(directory_build + "/libboost_system.dylib")
|
||||
base.copy_files(directory_build + "/linux_64/*.a", directory_build)
|
||||
# TODO: support x86
|
||||
|
||||
if config.check_option("platform", "linux_arm64") and not base.is_dir("../build/linux_arm64"):
|
||||
|
||||
@ -9,11 +9,24 @@ import qmake
|
||||
|
||||
def make(src_dir, modules, build_platform="android", qmake_addon=""):
|
||||
old_cur = os.getcwd()
|
||||
old_env = dict(os.environ)
|
||||
b2_addon = ""
|
||||
|
||||
print("boost-headers...")
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=system"])
|
||||
base.cmd("./b2", ["--prefix=./../build/" + build_platform, "headers", "install"])
|
||||
|
||||
|
||||
# for b2 checks
|
||||
if config.option("sysroot") != "":
|
||||
base.set_sysroot_env()
|
||||
b2_addon = "cflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
b2_addon = "cxxflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
b2_addon = "linkflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=system"])
|
||||
base.cmd("./b2", ["--prefix=./../build/" + build_platform, "headers", "install", b2_addon])
|
||||
|
||||
if config.option("sysroot") != "":
|
||||
base.restore_sysroot_env()
|
||||
|
||||
for module in modules:
|
||||
print("boost-module: " + module + " ...")
|
||||
module_dir = src_dir + "/libs/" + module
|
||||
@ -40,6 +53,8 @@ def make(src_dir, modules, build_platform="android", qmake_addon=""):
|
||||
base.save_as_script(module_dir + "/" + module + ".pro", pro_file_content)
|
||||
os.chdir(module_dir)
|
||||
qmake.make_all_platforms(module_dir + "/" + module + ".pro", qmake_addon)
|
||||
|
||||
|
||||
os.environ.clear()
|
||||
os.environ.update(old_env)
|
||||
os.chdir(old_cur)
|
||||
return
|
||||
|
||||
@ -5,6 +5,13 @@ sys.path.append('../..')
|
||||
import config
|
||||
import base
|
||||
import os
|
||||
import glob
|
||||
|
||||
def clear_module():
|
||||
for child in glob.glob("./*"):
|
||||
if base.is_dir(child):
|
||||
base.delete_dir(child)
|
||||
return
|
||||
|
||||
def make():
|
||||
print("[fetch & build]: cef")
|
||||
@ -13,13 +20,14 @@ def make():
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp", "linux_64", "linux_32", "mac_64", "mac_arm64"]
|
||||
base.check_module_version("2", clear_module)
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp", "linux_64", "linux_32", "mac_64", "mac_arm64", "win_arm64"]
|
||||
|
||||
for platform in platforms:
|
||||
if not config.check_option("platform", platform):
|
||||
continue
|
||||
|
||||
url = "http://d2ettrnqo7v976.cloudfront.net/cef/"
|
||||
url = "https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/cef/"
|
||||
archive_name = "./cef_binary.7z"
|
||||
|
||||
if (-1 != platform.find("_xp")):
|
||||
|
||||
@ -8,7 +8,7 @@ import os
|
||||
|
||||
def clean():
|
||||
if base.is_dir("glew-2.1.0"):
|
||||
base.delete_dir("glew-2.1.0");
|
||||
base.delete_dir("glew-2.1.0")
|
||||
return
|
||||
|
||||
def make():
|
||||
@ -16,7 +16,7 @@ def make():
|
||||
return
|
||||
|
||||
if not config.check_option("module", "mobile"):
|
||||
return;
|
||||
return
|
||||
|
||||
print("[fetch & build]: glew")
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/glew"
|
||||
@ -26,7 +26,7 @@ def make():
|
||||
base.common_check_version("glew", "1", clean)
|
||||
|
||||
if not base.is_dir("glew-2.1.0"):
|
||||
base.download("https://deac-ams.dl.sourceforge.net/project/glew/glew/2.1.0/glew-2.1.0-win32.zip", "./archive.zip")
|
||||
base.download("https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/glew/glew-2.1.0-win32.zip", "./archive.zip")
|
||||
base.extract("./archive.zip", "./")
|
||||
base.delete_file("./archive.zip")
|
||||
|
||||
|
||||
415
scripts/core_common/modules/heif.py
Normal file
415
scripts/core_common/modules/heif.py
Normal file
@ -0,0 +1,415 @@
|
||||
import sys
|
||||
sys.path.append('../..')
|
||||
import base
|
||||
import os
|
||||
import config
|
||||
|
||||
# NOTE:
|
||||
# - requires CMake >= 3.21, < 4.0.0
|
||||
|
||||
# libs versions
|
||||
X265_VERSION = "4.1"
|
||||
DE265_VERSION = "1.0.16"
|
||||
# 1.18.2 - the latest version of libheif supporting C++11 builds (as for now)
|
||||
HEIF_VERSION = "1.18.2"
|
||||
|
||||
# ios cmake toolchain
|
||||
IOS_CMAKE_VERSION = "4.5.0"
|
||||
IOS_CMAKE_TOOLCHAIN_FILE = base.get_script_dir() + "/../../core/Common/3dParty/heif/ios-cmake/ios.toolchain.cmake"
|
||||
|
||||
# android cmake toolchain
|
||||
ANDROID_CMAKE_TOOLCHAIN_FILE = base.get_env("ANDROID_NDK_ROOT") + "/build/cmake/android.toolchain.cmake"
|
||||
|
||||
# linux arm64 cmake toolchain
|
||||
LINUX_ARM64_CMAKE_TOOLCHAIN_FILE = base.get_script_dir() + "/../tools/linux/arm/cross_arm64/linux-arm64.toolchain.cmake"
|
||||
|
||||
LINUX_CUSTOM_SYSROOT_TOOLCHAIN_FILE = base.get_script_dir() + "/../tools/linux/sysroot/custom-sysroot.toolchain.cmake"
|
||||
|
||||
OLD_ENV = dict()
|
||||
|
||||
# get custom sysroot vars as str
|
||||
def setup_custom_sysroot_env() -> str:
|
||||
env_vars = []
|
||||
env_vars += ['LD_LIBRARY_PATH=\"' + config.get_custom_sysroot_lib() + "\""]
|
||||
env_vars += ['PATH=\"' + config.option("sysroot") + "/usr/bin:" + base.get_env("PATH") + "\""]
|
||||
env_vars += ['CC=\"' + config.get_custom_sysroot_bin() + "/gcc\""]
|
||||
env_vars += ['CXX=\"' + config.get_custom_sysroot_bin() + "/g++\""]
|
||||
env_vars += ['AR=\"' + config.get_custom_sysroot_bin() + "/ar\""]
|
||||
env_vars += ['RABLIB=\"' + config.get_custom_sysroot_bin() + "/ranlib\""]
|
||||
env_vars += ['CFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
env_vars += ['CXXFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
env_vars += ['LDFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
|
||||
env_str = ""
|
||||
for env_var in env_vars:
|
||||
env_str += env_var + " "
|
||||
|
||||
return env_str
|
||||
|
||||
def get_vs_version():
|
||||
vs_version = "14 2015"
|
||||
if config.option("vs-version") == "2019":
|
||||
vs_version = "16 2019"
|
||||
return vs_version
|
||||
|
||||
def get_xcode_sdk(platform):
|
||||
xcode_sdk = "iphoneos"
|
||||
if "simulator" in platform:
|
||||
xcode_sdk = "iphonesimulator"
|
||||
return xcode_sdk
|
||||
|
||||
def fetch_repo(repo_url, branch_or_tag):
|
||||
base.cmd("git", ["clone", "--depth", "1", "--branch", branch_or_tag, repo_url])
|
||||
return
|
||||
|
||||
def get_build_dir(base_dir, repo_dir, platform, build_type):
|
||||
return os.path.join(base_dir, repo_dir, "build", platform, build_type.lower())
|
||||
|
||||
# general build function that builds for ONE platform (supposing we are located in the build directory)
|
||||
def build_with_cmake(platform, cmake_args, build_type):
|
||||
# extend cmake arguments
|
||||
cmake_args_ext = []
|
||||
# WINDOWS
|
||||
if "win" in platform:
|
||||
cmake_args_ext = [
|
||||
"-G", f"Visual Studio {get_vs_version()}"
|
||||
]
|
||||
if platform == "win_64" or platform == "win_64_xp":
|
||||
cmake_args_ext += ["-A", "x64"]
|
||||
elif platform == "win_32" or platform == "win_32_xp":
|
||||
cmake_args_ext += ["-A", "Win32"]
|
||||
elif platform == "win_arm64":
|
||||
cmake_args_ext += ["-A", "ARM64"]
|
||||
# LINUX, MAC
|
||||
elif "linux" in platform or "mac" in platform:
|
||||
cmake_args_ext = [
|
||||
"-G", "Unix Makefiles",
|
||||
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON" # on UNIX we need to compile with fPIC
|
||||
]
|
||||
if platform == "mac_64":
|
||||
cmake_args_ext += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11", "-DCMAKE_OSX_ARCHITECTURES=x86_64"]
|
||||
elif platform == "mac_arm64":
|
||||
cmake_args_ext += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0", "-DCMAKE_OSX_ARCHITECTURES=arm64"]
|
||||
elif platform == "linux_arm64":
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_ARM64_CMAKE_TOOLCHAIN_FILE]
|
||||
elif config.option("sysroot") != "":
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_CUSTOM_SYSROOT_TOOLCHAIN_FILE] # force use custom CXXFLAGS with Release/Debug build
|
||||
# IOS
|
||||
elif "ios" in platform:
|
||||
cmake_args_ext = [
|
||||
"-G", "Xcode",
|
||||
"-DCMAKE_TOOLCHAIN_FILE=" + IOS_CMAKE_TOOLCHAIN_FILE,
|
||||
"-DDEPLOYMENT_TARGET=11.0"
|
||||
]
|
||||
if platform == "ios":
|
||||
cmake_args_ext += ["-DPLATFORM=OS64"]
|
||||
elif platform == "ios_simulator":
|
||||
cmake_args_ext += ["-DPLATFORM=SIMULATOR64COMBINED"]
|
||||
# ANDROID
|
||||
elif "android" in platform:
|
||||
cmake_args_ext = [
|
||||
"-G", "Unix Makefiles",
|
||||
"-DCMAKE_TOOLCHAIN_FILE=" + ANDROID_CMAKE_TOOLCHAIN_FILE,
|
||||
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
|
||||
]
|
||||
def get_cmake_args_android(arch, api_level):
|
||||
return [
|
||||
"-DANDROID_ABI=" + arch,
|
||||
"-DANDROID_NATIVE_API_LEVEL=" + api_level
|
||||
]
|
||||
if platform == "android_arm64_v8a":
|
||||
cmake_args_ext += get_cmake_args_android("arm64-v8a", "21")
|
||||
elif platform == "android_armv7":
|
||||
cmake_args_ext += get_cmake_args_android("armeabi-v7a", "16")
|
||||
elif platform == "android_x86":
|
||||
cmake_args_ext += get_cmake_args_android("x86", "16")
|
||||
elif platform == "android_x86_64":
|
||||
cmake_args_ext += get_cmake_args_android("x86_64", "21")
|
||||
|
||||
# env setup for custom sysroot
|
||||
env_str = setup_custom_sysroot_env() if config.option("sysroot") != "" else ""
|
||||
|
||||
# run cmake
|
||||
base.cmd(env_str + "cmake", cmake_args + cmake_args_ext)
|
||||
|
||||
# build
|
||||
if "Unix Makefiles" in cmake_args_ext:
|
||||
base.cmd(env_str + "make", ["-j4"])
|
||||
else:
|
||||
base.cmd("cmake", ["--build", ".", "--config", build_type])
|
||||
return
|
||||
|
||||
# general make function that calls `build_func` callback for configured platform(s) with specified cmake arguments
|
||||
def make_common(build_func, cmake_args):
|
||||
# WINDOWS
|
||||
if "windows" == base.host_platform():
|
||||
# win_64
|
||||
if config.check_option("platform", "win_64") or config.check_option("platform", "win_64_xp"):
|
||||
build_func("win_64", cmake_args)
|
||||
# win_32
|
||||
if config.check_option("platform", "win_32") or config.check_option("platform", "win_32_xp"):
|
||||
build_func("win_32", cmake_args)
|
||||
# win_arm64
|
||||
if config.check_option("platform", "win_arm64"):
|
||||
build_func("win_arm64", cmake_args)
|
||||
|
||||
# LINUX
|
||||
elif "linux" == base.host_platform():
|
||||
# linux_64
|
||||
if config.check_option("platform", "linux_64"):
|
||||
build_func("linux_64", cmake_args)
|
||||
# linux_arm64
|
||||
if config.check_option("platform", "linux_arm64"):
|
||||
build_func("linux_arm64", cmake_args)
|
||||
|
||||
# MAC
|
||||
elif "mac" == base.host_platform():
|
||||
# mac_64
|
||||
if config.check_option("platform", "mac_64"):
|
||||
build_func("mac_64", cmake_args)
|
||||
# mac_arm64
|
||||
if config.check_option("platform", "mac_arm64"):
|
||||
build_func("mac_arm64", cmake_args)
|
||||
|
||||
# IOS
|
||||
if -1 != config.option("platform").find("ios"):
|
||||
# ios (arm64)
|
||||
build_func("ios", cmake_args)
|
||||
# ios simulator (x86_64 and arm64 FAT lib)
|
||||
build_func("ios_simulator", cmake_args)
|
||||
|
||||
# ANDROID
|
||||
if -1 != config.option("platform").find("android"):
|
||||
# android_arm64_v8a
|
||||
if config.check_option("platform", "android_arm64_v8a"):
|
||||
build_func("android_arm64_v8a", cmake_args)
|
||||
# android_armv7
|
||||
if config.check_option("platform", "android_armv7"):
|
||||
build_func("android_armv7", cmake_args)
|
||||
# android_x86
|
||||
if config.check_option("platform", "android_x86"):
|
||||
build_func("android_x86", cmake_args)
|
||||
# android_x86_64
|
||||
if config.check_option("platform", "android_x86_64"):
|
||||
build_func("android_x86_64", cmake_args)
|
||||
|
||||
return
|
||||
|
||||
def make_x265(base_dir, build_type):
|
||||
# fetch lib repo
|
||||
if not base.is_dir("x265_git"):
|
||||
fetch_repo("https://bitbucket.org/multicoreware/x265_git.git", f"Release_{X265_VERSION}")
|
||||
# fix x265 version detection so it reads version from x265Version.txt instead of parsing it from .git
|
||||
base.replaceInFile(
|
||||
base_dir + "/x265_git/source/cmake/Version.cmake",
|
||||
"elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../x265Version.txt)",
|
||||
"endif()\n if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../x265Version.txt)"
|
||||
)
|
||||
|
||||
# prepare cmake args
|
||||
cmake_dir = base_dir + "/x265_git/source"
|
||||
cmake_args = [
|
||||
cmake_dir,
|
||||
"-DCMAKE_BUILD_TYPE=" + build_type,
|
||||
"-DENABLE_CLI=OFF", # do not build standalone CLI app
|
||||
"-DENABLE_SHARED=OFF", # do not build shared libs
|
||||
"-DENABLE_ASSEMBLY=OFF", # disable assembly optimizations
|
||||
"-DENABLE_LIBNUMA=OFF", # disable libnuma usage (affects Linux only)
|
||||
]
|
||||
|
||||
# lib build function
|
||||
def build_x265(platform, cmake_args):
|
||||
# check if target lib has already been built
|
||||
build_dir = get_build_dir(base_dir, "x265_git", platform, build_type)
|
||||
if platform.find("win") != -1:
|
||||
target_lib = os.path.join(build_dir, build_type, "x265-static.lib")
|
||||
else:
|
||||
target_lib = os.path.join(build_dir, "libx265.a")
|
||||
if base.is_file(target_lib):
|
||||
return
|
||||
# go to the build directory
|
||||
base.create_dir(build_dir)
|
||||
os.chdir(build_dir)
|
||||
# run build
|
||||
build_with_cmake(platform, cmake_args, build_type)
|
||||
# for iOS there is no target for building libx265.a, so we need to form it ourselves from libcommon.a and libencoder.a
|
||||
if platform.find("ios") != -1:
|
||||
xcode_sdk = get_xcode_sdk(platform)
|
||||
base.cmd("libtool", [
|
||||
"-static",
|
||||
"-o", "libx265.a",
|
||||
f"build/common.build/{build_type}-{xcode_sdk}/libcommon.a",
|
||||
f"build/encoder.build/{build_type}-{xcode_sdk}/libencoder.a"
|
||||
])
|
||||
# copy header
|
||||
base.copy_file(base_dir + "/x265_git/source/x265.h", build_dir)
|
||||
# reset directory
|
||||
os.chdir(base_dir)
|
||||
return
|
||||
|
||||
make_common(build_x265, cmake_args)
|
||||
return
|
||||
|
||||
def make_de265(base_dir, build_type):
|
||||
# fetch lib repo
|
||||
if not base.is_dir("libde265"):
|
||||
fetch_repo("https://github.com/strukturag/libde265.git", f"v{DE265_VERSION}")
|
||||
|
||||
# prepare cmake args
|
||||
cmake_dir = base_dir + "/libde265"
|
||||
cmake_args = [
|
||||
cmake_dir,
|
||||
"-DCMAKE_BUILD_TYPE=" + build_type,
|
||||
"-DBUILD_SHARED_LIBS=OFF", # do not build shared libs
|
||||
"-DENABLE_SDL=OFF", # disable SDL
|
||||
"-DENABLE_DECODER=OFF", # do not build decoder CLI executable
|
||||
"-DENABLE_ENCODER=OFF", # do not build encoder CLI executable
|
||||
]
|
||||
|
||||
# lib build function
|
||||
def build_de265(platform, cmake_args):
|
||||
# check if target lib has already been built
|
||||
build_dir = get_build_dir(base_dir, "libde265", platform, build_type)
|
||||
if platform.find("win") != -1:
|
||||
target_lib = os.path.join(build_dir, "libde265", build_type, "libde265.lib")
|
||||
else:
|
||||
target_lib = os.path.join(build_dir, "libde265/libde265.a")
|
||||
if base.is_file(target_lib):
|
||||
return
|
||||
# go to the build directory
|
||||
base.create_dir(build_dir)
|
||||
os.chdir(build_dir)
|
||||
# run build
|
||||
build_with_cmake(platform, cmake_args, build_type)
|
||||
# for ios copy target library from the default build path
|
||||
if platform.find("ios") != -1:
|
||||
xcode_sdk = get_xcode_sdk(platform)
|
||||
base.copy_file(f"libde265/{build_type}-{xcode_sdk}/libde265.a", "libde265")
|
||||
# copy header
|
||||
base.copy_file(base_dir + "/libde265/libde265/de265.h", "libde265")
|
||||
# reset directory
|
||||
os.chdir(base_dir)
|
||||
return
|
||||
|
||||
make_common(build_de265, cmake_args)
|
||||
return
|
||||
|
||||
def make_heif(base_dir, build_type):
|
||||
# fetch lib repo
|
||||
if not base.is_dir("libheif"):
|
||||
fetch_repo("https://github.com/strukturag/libheif.git", f"v{HEIF_VERSION}")
|
||||
# do not build heifio module
|
||||
base.replaceInFile(
|
||||
base_dir + "/libheif/CMakeLists.txt",
|
||||
"add_subdirectory(heifio)",
|
||||
"# add_subdirectory(heifio)"
|
||||
)
|
||||
base.replaceInFile(
|
||||
base_dir + "/libheif/CMakeLists.txt",
|
||||
"if (DOXYGEN_FOUND)",
|
||||
"if (FALSE)"
|
||||
)
|
||||
|
||||
# prepare cmake args
|
||||
cmake_dir = base_dir + "/libheif"
|
||||
cmake_args = [
|
||||
cmake_dir,
|
||||
"--preset=release-noplugins", # preset to disable plugins system
|
||||
"-DCMAKE_BUILD_TYPE=" + build_type,
|
||||
"-DBUILD_SHARED_LIBS=OFF", # do not build shared libs
|
||||
"-DWITH_LIBSHARPYUV=OFF", # do not build libsharpyuv (for RGB <--> YUV color space conversions)
|
||||
"-DWITH_AOM_DECODER=OFF", # do not build AOM V1 decoder (for AVIF image format)
|
||||
"-DWITH_AOM_ENCODER=OFF", # do not build AOM V1 encoder (for AVIF image format)
|
||||
"-DWITH_GDK_PIXBUF=OFF", # do not build gdk-pixbuf plugin (UNIX only)
|
||||
"-DWITH_GNOME=OFF", # do not build gnome plugin (Linux only)
|
||||
"-DWITH_EXAMPLES=OFF", # do not build examples
|
||||
"-DWITH_EXAMPLE_HEIF_VIEW=OFF", # do not build heif-view CLI tool
|
||||
"-DWITH_X265=ON", # enable x265 codec
|
||||
"-DWITH_LIBDE265=ON", # enable de265 codec
|
||||
"-DCMAKE_CXX_FLAGS=-DLIBDE265_STATIC_BUILD", # add macro definition to properly compile with de265 static library
|
||||
"-DCMAKE_C_FLAGS=-DLIBDE265_STATIC_BUILD", # same ^
|
||||
]
|
||||
|
||||
# lib build function
|
||||
def build_heif(platform, cmake_args):
|
||||
# check if target lib has already been built
|
||||
build_dir = get_build_dir(base_dir, "libheif", platform, build_type)
|
||||
if platform.find("win") != -1:
|
||||
target_lib = os.path.join(build_dir, "libheif", build_type, "heif.lib")
|
||||
else:
|
||||
target_lib = os.path.join(build_dir, "libheif/libheif.a")
|
||||
if base.is_file(target_lib):
|
||||
return
|
||||
# go to the build directory
|
||||
base.create_dir(build_dir)
|
||||
os.chdir(build_dir)
|
||||
# add paths to dependent libraries and includes to cmake args
|
||||
de265_build_dir = get_build_dir(base_dir, "libde265", platform, build_type)
|
||||
x265_build_dir = get_build_dir(base_dir, "x265_git", platform, build_type)
|
||||
cmake_args_ext = [
|
||||
f"-DLIBDE265_INCLUDE_DIR={de265_build_dir}",
|
||||
f"-DX265_INCLUDE_DIR={x265_build_dir}"
|
||||
]
|
||||
if platform.find("win") != -1:
|
||||
cmake_args_ext += [
|
||||
f"-DLIBDE265_LIBRARY={de265_build_dir}/libde265/{build_type}/libde265.lib",
|
||||
f"-DX265_LIBRARY={x265_build_dir}/{build_type}/x265-static.lib"
|
||||
]
|
||||
else:
|
||||
cmake_args_ext += [
|
||||
f"-DLIBDE265_LIBRARY={de265_build_dir}/libde265/libde265.a",
|
||||
f"-DX265_LIBRARY={x265_build_dir}/libx265.a"
|
||||
]
|
||||
# run build
|
||||
build_with_cmake(platform, cmake_args + cmake_args_ext, build_type)
|
||||
# for ios copy target library from the default build path
|
||||
if platform.find("ios") != -1:
|
||||
xcode_sdk = get_xcode_sdk(platform)
|
||||
base.copy_file(f"libheif/{build_type}-{xcode_sdk}/libheif.a", "libheif")
|
||||
# reset directory
|
||||
os.chdir(base_dir)
|
||||
return
|
||||
|
||||
make_common(build_heif, cmake_args)
|
||||
return
|
||||
|
||||
def clear_module():
|
||||
if base.is_dir("libde265"):
|
||||
base.delete_dir_with_access_error("libde265")
|
||||
if base.is_dir("x265_git"):
|
||||
base.delete_dir_with_access_error("x265_git")
|
||||
if base.is_dir("libheif"):
|
||||
base.delete_dir_with_access_error("libheif")
|
||||
return
|
||||
|
||||
def make():
|
||||
print("[fetch & build]: heif")
|
||||
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/heif"
|
||||
old_dir = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
|
||||
base.check_module_version("2", clear_module)
|
||||
|
||||
build_type = "Release"
|
||||
if (-1 != config.option("config").lower().find("debug")):
|
||||
build_type = "Debug"
|
||||
|
||||
# fetch custom cmake toolchain for ios
|
||||
if -1 != config.option("platform").find("ios"):
|
||||
if not base.is_file(IOS_CMAKE_TOOLCHAIN_FILE):
|
||||
fetch_repo("https://github.com/leetal/ios-cmake.git", IOS_CMAKE_VERSION)
|
||||
|
||||
# build encoder library
|
||||
make_x265(base_dir, build_type)
|
||||
# build decoder library
|
||||
make_de265(base_dir, build_type)
|
||||
|
||||
# build libheif
|
||||
make_heif(base_dir, build_type)
|
||||
|
||||
os.chdir(old_dir)
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
make()
|
||||
@ -7,7 +7,27 @@ import base
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def clear_module():
|
||||
directories = ["gumbo-parser", "katana-parser"]
|
||||
|
||||
for dir in directories:
|
||||
if base.is_dir(dir):
|
||||
base.delete_dir_with_access_error(dir)
|
||||
|
||||
def make():
|
||||
old_cur_dir = os.getcwd()
|
||||
|
||||
print("[fetch]: html")
|
||||
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/html"
|
||||
|
||||
os.chdir(base_dir)
|
||||
base.check_module_version("2", clear_module)
|
||||
os.chdir(old_cur_dir)
|
||||
|
||||
base.cmd_in_dir(base_dir, "python", ["fetch.py"])
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
# manual compile
|
||||
make()
|
||||
|
||||
@ -3,6 +3,11 @@ sys.path.append('../../../scripts')
|
||||
import base
|
||||
import os
|
||||
|
||||
def clean():
|
||||
if base.is_dir("hunspell"):
|
||||
base.delete_dir_with_access_error("hunspell")
|
||||
return
|
||||
|
||||
def make(build_js = True):
|
||||
|
||||
old_cur_dir = os.getcwd()
|
||||
@ -11,6 +16,8 @@ def make(build_js = True):
|
||||
core_common_dir = base.get_script_dir() + "/../../core/Common"
|
||||
|
||||
os.chdir(core_common_dir + "/3dParty/hunspell")
|
||||
|
||||
base.common_check_version("hunspell", "1", clean)
|
||||
base.cmd("python", ["./before.py"])
|
||||
|
||||
if (build_js):
|
||||
|
||||
@ -9,11 +9,12 @@ import os
|
||||
import glob
|
||||
import icu_android
|
||||
|
||||
def fetch_icu(major, minor):
|
||||
base.cmd("git", ["clone", "--depth", "1", "--branch", "maint/maint-" + major, "https://github.com/unicode-org/icu.git", "./icu2"])
|
||||
base.copy_dir("./icu2/icu4c", "./icu")
|
||||
def fetch_icu(major, minor, target_dir="icu"):
|
||||
if (base.is_dir("./icu2")):
|
||||
base.delete_dir_with_access_error("icu2")
|
||||
base.cmd("git", ["clone", "--depth", "1", "--branch", "release-" + major + "-" + minor, "https://github.com/unicode-org/icu.git", "./icu2"])
|
||||
base.copy_dir("./icu2/icu4c", target_dir)
|
||||
base.delete_dir_with_access_error("icu2")
|
||||
#base.cmd("svn", ["export", "https://github.com/unicode-org/icu/tags/release-" + icu_major + "-" + icu_minor + "/icu4c", "./icu", "--non-interactive", "--trust-server-cert"])
|
||||
return
|
||||
|
||||
def clear_module():
|
||||
@ -34,18 +35,26 @@ def make():
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
|
||||
base.check_module_version("3", clear_module)
|
||||
base.check_module_version("7", clear_module)
|
||||
|
||||
if (-1 != config.option("platform").find("android")):
|
||||
icu_android.make()
|
||||
|
||||
os.chdir(base_dir)
|
||||
|
||||
icu_major = "58"
|
||||
icu_minor = "3"
|
||||
|
||||
icu_major = "74"
|
||||
icu_minor = "2"
|
||||
|
||||
if not base.is_dir("icu"):
|
||||
fetch_icu(icu_major, icu_minor)
|
||||
fetch_icu(icu_major, icu_minor)
|
||||
|
||||
# old version for win_xp
|
||||
icu_major_old = "58"
|
||||
icu_minor_old = "3"
|
||||
|
||||
if config.check_option("platform", "win_64_xp") or config.check_option("platform", "win_32_xp"):
|
||||
if not base.is_dir("icu58"):
|
||||
fetch_icu(icu_major_old, icu_minor_old, "icu58")
|
||||
|
||||
if ("windows" == base.host_platform()):
|
||||
platformToolset = "v140"
|
||||
@ -56,53 +65,103 @@ def make():
|
||||
need_platforms.append("win_64")
|
||||
if (-1 != config.option("platform").find("win_32")):
|
||||
need_platforms.append("win_32")
|
||||
if (-1 != config.option("platform").find("win_arm64")):
|
||||
need_platforms.append("win_64") # for exe files
|
||||
need_platforms.append("win_arm64")
|
||||
|
||||
def build_icu_win(source_dir, out_dir, icu_major):
|
||||
if base.is_dir(out_dir):
|
||||
return
|
||||
|
||||
compile_bat = []
|
||||
compile_bat.append("setlocal")
|
||||
|
||||
args = {
|
||||
"win_32" : {
|
||||
"msbuild_platfrom" : "Win32",
|
||||
"vcvarsall_arch" : "x86",
|
||||
"out_bin_dir" : source_dir + "/bin/",
|
||||
"out_lib_dir" : source_dir + "/lib/"
|
||||
},
|
||||
"win_64" : {
|
||||
"msbuild_platfrom" : "X64",
|
||||
"vcvarsall_arch" : "x64",
|
||||
"out_bin_dir" : source_dir + "/bin64/",
|
||||
"out_lib_dir" : source_dir + "/lib64/"
|
||||
},
|
||||
"win_arm64" : {
|
||||
"msbuild_platfrom" : "ARM64",
|
||||
"vcvarsall_arch" : "x64_arm64",
|
||||
"out_bin_dir" : source_dir + "/binARM64/",
|
||||
"out_lib_dir" : source_dir + "/libARM64/"
|
||||
}
|
||||
}
|
||||
|
||||
platform_args = args[platform]
|
||||
|
||||
compile_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + platform_args['vcvarsall_arch'])
|
||||
compile_bat.append("call MSBuild.exe " + source_dir + "/source/allinone/allinone.sln /p:Configuration=Release /p:PlatformToolset=" + platformToolset + " /p:Platform=" + platform_args['msbuild_platfrom'])
|
||||
compile_bat.append("endlocal")
|
||||
base.run_as_bat(compile_bat)
|
||||
|
||||
base.create_dir(out_dir)
|
||||
base.copy_file(platform_args['out_bin_dir'] + "icudt" + icu_major + ".dll", out_dir)
|
||||
base.copy_file(platform_args['out_bin_dir'] + "icuuc" + icu_major + ".dll", out_dir)
|
||||
base.copy_file(platform_args['out_lib_dir'] + "icudt.lib", out_dir)
|
||||
base.copy_file(platform_args['out_lib_dir'] + "icuuc.lib", out_dir)
|
||||
|
||||
for platform in need_platforms:
|
||||
if not config.check_option("platform", platform) and not config.check_option("platform", platform + "_xp"):
|
||||
continue
|
||||
if not base.is_dir(platform + "/build"):
|
||||
base.create_dir(platform)
|
||||
compile_bat = []
|
||||
compile_bat.append("setlocal")
|
||||
compile_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + ("x86" if base.platform_is_32(platform) else "x64"))
|
||||
compile_bat.append("call MSBuild.exe icu/source/allinone/allinone.sln /p:Configuration=Release /p:PlatformToolset=" + platformToolset + " /p:Platform=" + ("Win32" if base.platform_is_32(platform) else "X64"))
|
||||
compile_bat.append("endlocal")
|
||||
base.run_as_bat(compile_bat)
|
||||
bin_dir = "icu/bin64/" if ("win_64" == platform) else "icu/bin/"
|
||||
lib_dir = "icu/lib64/" if ("win_64" == platform) else "icu/lib/"
|
||||
base.create_dir(platform + "/build")
|
||||
base.copy_file(bin_dir + "icudt" + icu_major + ".dll", platform + "/build/")
|
||||
base.copy_file(bin_dir + "icuuc" + icu_major + ".dll", platform + "/build/")
|
||||
base.copy_file(lib_dir + "icudt.lib", platform + "/build/")
|
||||
base.copy_file(lib_dir + "icuuc.lib", platform + "/build/")
|
||||
|
||||
if not (config.check_option("platform", "win_64_xp") or config.check_option("platform", "win_32_xp")):
|
||||
build_icu_win("icu", platform + "/build", icu_major)
|
||||
else:
|
||||
# xp
|
||||
build_icu_win("icu58", platform + "/build/xp", icu_major_old)
|
||||
|
||||
os.chdir(old_cur)
|
||||
return
|
||||
|
||||
if ("linux" == base.host_platform()):
|
||||
if not base.is_file("./icu/source/i18n/digitlst.cpp.bak"):
|
||||
base.copy_file("./icu/source/i18n/digitlst.cpp", "./icu/source/i18n/digitlst.cpp.bak")
|
||||
base.replaceInFile("./icu/source/i18n/digitlst.cpp", "xlocale", "locale")
|
||||
if base.is_dir(base_dir + "/linux_64"):
|
||||
base.delete_dir(base_dir + "/linux_64")
|
||||
if base.is_dir(base_dir + "/linux_arm64"):
|
||||
base.delete_dir(base_dir + "/linux_arm64")
|
||||
|
||||
if not base.is_dir(base_dir + "/linux_64"):
|
||||
base.create_dir(base_dir + "/icu/cross_build")
|
||||
os.chdir("icu/cross_build")
|
||||
base.cmd("./../source/runConfigureICU", ["Linux", "--prefix=" + base_dir + "/icu/cross_build_install"])
|
||||
base.replaceInFile("./../source/icudefs.mk.in", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS) -static-libstdc++ -static-libgcc")
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"], True)
|
||||
command_configure = "./../source/runConfigureICU"
|
||||
command_compile_addon = "-static-libstdc++ -static-libgcc"
|
||||
if "1" == config.option("use-clang"):
|
||||
command_configure = "CXXFLAGS=-stdlib=libc++ " + command_configure
|
||||
command_compile_addon = "-stdlib=libc++"
|
||||
if "" == config.option("sysroot"):
|
||||
base.cmd(command_configure, ["Linux", "--prefix=" + base_dir + "/icu/cross_build_install"])
|
||||
base.replaceInFile("./../source/icudefs.mk.in", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS) " + command_compile_addon)
|
||||
else:
|
||||
base.set_sysroot_env()
|
||||
base.cmd_exe("./../source/configure", ["--prefix=" + base_dir + "/icu/cross_build_install",
|
||||
"CC=" + config.get_custom_sysroot_bin() + "/gcc", "CXX=" + config.get_custom_sysroot_bin() + "/g++",
|
||||
"AR=" + config.get_custom_sysroot_bin() + "/ar", "RANLIB=" + config.get_custom_sysroot_bin() + "/ranlib",
|
||||
"CFLAGS=--sysroot=" + config.option("sysroot"),
|
||||
"CXXFLAGS=--sysroot=" + config.option("sysroot") + " " + command_compile_addon,
|
||||
"LDFLAGS=--sysroot=" + config.option("sysroot")])
|
||||
|
||||
if "" == config.option("sysroot"):
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"], True)
|
||||
else:
|
||||
base.cmd_exe("make", ["-j4"])
|
||||
base.cmd_exe("make", ["install"], True)
|
||||
base.restore_sysroot_env()
|
||||
|
||||
base.create_dir(base_dir + "/linux_64")
|
||||
base.create_dir(base_dir + "/linux_64/build")
|
||||
base.copy_file(base_dir + "/icu/cross_build_install/lib/libicudata.so." + icu_major + "." + icu_minor, base_dir + "/linux_64/build/libicudata.so." + icu_major)
|
||||
base.copy_file(base_dir + "/icu/cross_build_install/lib/libicuuc.so." + icu_major + "." + icu_minor, base_dir + "/linux_64/build/libicuuc.so." + icu_major)
|
||||
base.copy_dir(base_dir + "/icu/cross_build_install/include", base_dir + "/linux_64/build/include")
|
||||
|
||||
|
||||
if config.check_option("platform", "linux_arm64") and not base.is_dir(base_dir + "/linux_arm64") and not base.is_os_arm():
|
||||
base.create_dir(base_dir + "/icu/linux_arm64")
|
||||
os.chdir(base_dir + "/icu/linux_arm64")
|
||||
base_arm_tool_dir = base.get_prefix_cross_compiler_arm64()
|
||||
base_arm_tool_dir = config.option('arm64-toolchain-bin') + '/' + base.get_prefix_cross_compiler_arm64()
|
||||
base.cmd("./../source/configure", ["--host=arm-linux", "--prefix=" + base_dir + "/icu/linux_arm64_install", "--with-cross-build=" + base_dir + "/icu/cross_build",
|
||||
"CC=" + base_arm_tool_dir + "gcc", "CXX=" + base_arm_tool_dir + "g++", "AR=" + base_arm_tool_dir + "ar", "RANLIB=" + base_arm_tool_dir + "ranlib"])
|
||||
base.cmd("make", ["-j4"])
|
||||
@ -128,6 +187,6 @@ def make():
|
||||
if (-1 != config.option("platform").find("ios")):
|
||||
if not base.is_dir("build"):
|
||||
base.bash("./icu_ios")
|
||||
|
||||
|
||||
os.chdir(old_cur)
|
||||
return
|
||||
|
||||
@ -5,37 +5,29 @@ sys.path.append('../..')
|
||||
import base
|
||||
import os
|
||||
|
||||
def change_icu_defs(current_dir, arch):
|
||||
icudef_file = current_dir + "/icudefs.mk"
|
||||
icudef_file_old = current_dir + "/icudefs.mk.back"
|
||||
def change_icu_defs(arch):
|
||||
old_env = dict(os.environ)
|
||||
|
||||
param = "-arch x86_64"
|
||||
if arch == "arm64":
|
||||
param = "-arch arm64 -isysroot " + base.find_mac_sdk()
|
||||
param = "-arch arm64"
|
||||
|
||||
param += " -isysroot " + base.find_mac_sdk()
|
||||
param += " -mmacosx-version-min=10.12"
|
||||
|
||||
base.copy_file(icudef_file, icudef_file_old)
|
||||
os.environ["CFLAGS"] = param
|
||||
os.environ["CXXFLAGS"] = param + " --std=c++11"
|
||||
os.environ["LDFLAGS"] = param
|
||||
|
||||
base.replaceInFile(icudef_file, "CFLAGS = ", "CFLAGS = " + param + " ")
|
||||
base.replaceInFile(icudef_file, "CXXFLAGS = ", "CXXFLAGS = " + param + " ")
|
||||
base.replaceInFile(icudef_file, "RPATHLDFLAGS =", "RPATHLDFLAGS2 =")
|
||||
base.replaceInFile(icudef_file, "LDFLAGS = ", "LDFLAGS = " + param + " ")
|
||||
base.replaceInFile(icudef_file, "RPATHLDFLAGS2 =", "RPATHLDFLAGS =")
|
||||
return old_env
|
||||
|
||||
def restore_icu_defs(old_env):
|
||||
os.environ.clear()
|
||||
os.environ.update(old_env)
|
||||
return
|
||||
|
||||
def restore_icu_defs(current_dir):
|
||||
icudef_file = current_dir + "/icudefs.mk"
|
||||
icudef_file_old = current_dir + "/icudefs.mk.back"
|
||||
|
||||
base.delete_file(icudef_file)
|
||||
base.copy_file(icudef_file_old, icudef_file)
|
||||
base.delete_file(icudef_file_old)
|
||||
return
|
||||
|
||||
icu_major = "58"
|
||||
icu_minor = "3"
|
||||
icu_major = "74"
|
||||
icu_minor = "2"
|
||||
|
||||
current_dir_old = os.getcwd()
|
||||
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/icu"
|
||||
@ -46,29 +38,33 @@ if not base.is_dir(current_dir + "/mac_cross_64"):
|
||||
base.create_dir(current_dir + "/mac_cross_64")
|
||||
os.chdir(current_dir + "/mac_cross_64")
|
||||
|
||||
base.cmd("../icu/source/runConfigureICU", ["MacOSX",
|
||||
"--prefix=" + current_dir + "/mac_cross_64", "CFLAGS=-Os CXXFLAGS=--std=c++11"])
|
||||
old_env = change_icu_defs("x86_64")
|
||||
|
||||
change_icu_defs(current_dir + "/mac_cross_64", "x86_64")
|
||||
base.cmd("../icu/source/runConfigureICU", ["MacOSX",
|
||||
"--prefix=" + current_dir + "/mac_cross_64", "--enable-static"])
|
||||
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"], True)
|
||||
|
||||
restore_icu_defs(current_dir + "/mac_cross_64")
|
||||
restore_icu_defs(old_env)
|
||||
|
||||
os.chdir(current_dir)
|
||||
|
||||
os.chdir(current_dir + "/icu/source")
|
||||
|
||||
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm_64",
|
||||
"--with-cross-build=" + current_dir + "/mac_cross_64", "VERBOSE=1"])
|
||||
old_env = change_icu_defs("arm64")
|
||||
|
||||
change_icu_defs(current_dir + "/icu/source", "arm64")
|
||||
addon = []
|
||||
if not base.is_os_arm():
|
||||
addon = ["--host=aarch64-apple-darwin"]
|
||||
|
||||
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm_64",
|
||||
"--with-cross-build=" + current_dir + "/mac_cross_64", "--enable-static", "VERBOSE=1"] + addon)
|
||||
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"])
|
||||
|
||||
restore_icu_defs(current_dir + "/icu/source")
|
||||
restore_icu_defs(old_env)
|
||||
|
||||
os.chdir(current_dir)
|
||||
|
||||
@ -85,12 +81,22 @@ base.create_dir(current_dir + "/mac_arm64")
|
||||
base.create_dir(current_dir + "/mac_arm64/build")
|
||||
|
||||
base.copy_dir(current_dir + "/mac_cross_64/include", current_dir + "/mac_64/build/include")
|
||||
# copy shared libs
|
||||
base.copy_file(current_dir + "/mac_cross_64/lib/libicudata." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_64/build/libicudata." + icu_major + ".dylib")
|
||||
base.copy_file(current_dir + "/mac_cross_64/lib/libicuuc." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_64/build/libicuuc." + icu_major + ".dylib")
|
||||
# copy static libs
|
||||
base.copy_file(current_dir + "/mac_cross_64/lib/libicudata.a", current_dir + "/mac_64/build")
|
||||
base.copy_file(current_dir + "/mac_cross_64/lib/libicui18n.a", current_dir + "/mac_64/build")
|
||||
base.copy_file(current_dir + "/mac_cross_64/lib/libicuuc.a", current_dir + "/mac_64/build")
|
||||
|
||||
base.copy_dir(current_dir + "/mac_arm_64/include", current_dir + "/mac_arm64/build/include")
|
||||
# copy shared libs
|
||||
base.copy_file(current_dir + "/mac_arm_64/lib/libicudata." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_arm64/build/libicudata." + icu_major + ".dylib")
|
||||
base.copy_file(current_dir + "/mac_arm_64/lib/libicuuc." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_arm64/build/libicuuc." + icu_major + ".dylib")
|
||||
# copy static libs
|
||||
base.copy_file(current_dir + "/mac_arm_64/lib/libicudata.a", current_dir + "/mac_arm64/build")
|
||||
base.copy_file(current_dir + "/mac_arm_64/lib/libicui18n.a", current_dir + "/mac_arm64/build")
|
||||
base.copy_file(current_dir + "/mac_arm_64/lib/libicuuc.a", current_dir + "/mac_arm64/build")
|
||||
|
||||
base.delete_dir(current_dir + "/mac_cross_64")
|
||||
base.delete_dir(current_dir + "/mac_arm_64")
|
||||
|
||||
38
scripts/core_common/modules/iwork.py
Normal file
38
scripts/core_common/modules/iwork.py
Normal file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../..')
|
||||
import config
|
||||
import base
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def clear_module():
|
||||
directories = ["glm", "libetonyek", "libodfgen", "librevenge", "mdds"]
|
||||
|
||||
for dir in directories:
|
||||
if base.is_dir(dir):
|
||||
base.delete_dir_with_access_error(dir)
|
||||
|
||||
def make(use_gperf = True):
|
||||
old_cur_dir = os.getcwd()
|
||||
|
||||
print("[fetch & build]: iwork")
|
||||
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/apple"
|
||||
|
||||
os.chdir(base_dir)
|
||||
base.check_module_version("3", clear_module)
|
||||
os.chdir(old_cur_dir)
|
||||
|
||||
cmd_args = ["fetch.py"]
|
||||
|
||||
if use_gperf:
|
||||
cmd_args.append("--gperf")
|
||||
|
||||
base.cmd_in_dir(base_dir, "python", cmd_args)
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
# manual compile
|
||||
make(False)
|
||||
20
scripts/core_common/modules/md.py
Normal file
20
scripts/core_common/modules/md.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../..')
|
||||
import config
|
||||
import base
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def make():
|
||||
print("[fetch]: md")
|
||||
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/md"
|
||||
|
||||
base.cmd_in_dir(base_dir, "python", ["fetch.py"])
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
# manual compile
|
||||
make()
|
||||
15
scripts/core_common/modules/oo_brotli.py
Normal file
15
scripts/core_common/modules/oo_brotli.py
Normal file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../..')
|
||||
import base
|
||||
import os
|
||||
|
||||
def make():
|
||||
print("[fetch & build]: brotli")
|
||||
base.cmd_in_dir(base.get_script_dir() + "/../../core/Common/3dParty/brotli", "./make.py")
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
# manual compile
|
||||
make()
|
||||
@ -54,6 +54,14 @@ def make():
|
||||
qmake_bat.append("call nmake clean")
|
||||
qmake_bat.append("call nmake build_libs install")
|
||||
base.run_as_bat(qmake_bat, True)
|
||||
if (-1 != config.option("platform").find("win_arm64")) and not base.is_dir("../build/win_arm64"):
|
||||
base.create_dir("./../build/win_arm64")
|
||||
qmake_bat = []
|
||||
qmake_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" x64_arm64")
|
||||
qmake_bat.append("perl Configure VC-WIN64-ARM --prefix=" + old_cur_dir + "\\build\\win_arm64 --openssldir=" + old_cur_dir + "\\build\\win_arm64 no-shared no-asm enable-md2")
|
||||
qmake_bat.append("call nmake clean")
|
||||
qmake_bat.append("call nmake build_libs install")
|
||||
base.run_as_bat(qmake_bat, True)
|
||||
os.chdir(old_cur)
|
||||
# xp ----------------------------------------------------------------------------------------------------
|
||||
os.chdir(base_dir + "/openssl")
|
||||
@ -79,14 +87,32 @@ def make():
|
||||
# -------------------------------------------------------------------------------------------------------
|
||||
return
|
||||
|
||||
if (-1 != config.option("platform").find("linux")) and not base.is_dir("../build/linux_64"):
|
||||
if (-1 != config.option("platform").find("linux")) and not base.is_dir("../build/linux_64"):
|
||||
base.cmd("./config", ["enable-md2", "no-shared", "no-asm", "--prefix=" + old_cur_dir + "/build/linux_64", "--openssldir=" + old_cur_dir + "/build/linux_64"])
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
base.cmd("make")
|
||||
base.cmd("make", ["install"])
|
||||
base.cmd("make", ["clean"], True)
|
||||
# TODO: support x86
|
||||
if "1" == config.option("use-clang"):
|
||||
base.replaceInFile("./Makefile", "CC=$(CROSS_COMPILE)gcc", "CC=$(CROSS_COMPILE)clang")
|
||||
base.replaceInFile("./Makefile", "CXX=$(CROSS_COMPILE)g++", "CXX=$(CROSS_COMPILE)clang++")
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden -stdlib=libc++")
|
||||
base.replaceInFile("./Makefile", "LDFLAGS=", "LDFLAGS=-stdlib=libc++")
|
||||
elif config.option("sysroot") == "":
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
else:
|
||||
base.replaceInFile("./Makefile", "CROSS_COMPILE=", "CROSS_COMPILE=" + config.get_custom_sysroot_bin() + "/")
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot"))
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot"))
|
||||
|
||||
if config.option("sysroot") == "":
|
||||
base.cmd("make", [])
|
||||
base.cmd("make", ["install"])
|
||||
base.cmd("make", ["clean"], True)
|
||||
else:
|
||||
base.set_sysroot_env()
|
||||
base.cmd_exe("make", [])
|
||||
base.cmd_exe("make", ["install"])
|
||||
base.cmd_exe("make", ["clean"], True)
|
||||
base.restore_sysroot_env()
|
||||
|
||||
if (-1 != config.option("platform").find("linux_arm64")) and not base.is_dir("../build/linux_arm64"):
|
||||
if ("x86_64" != platform.machine()):
|
||||
|
||||
@ -8,6 +8,11 @@ import os
|
||||
import subprocess
|
||||
import glob
|
||||
|
||||
def clean():
|
||||
if base.is_dir("socket.io-client-cpp"):
|
||||
base.delete_dir_with_access_error("socket.io-client-cpp")
|
||||
return
|
||||
|
||||
def correct_namespace(dir):
|
||||
folder = dir
|
||||
if ("/" != folder[-1:]):
|
||||
@ -25,6 +30,12 @@ def correct_namespace(dir):
|
||||
|
||||
def make():
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/socketio"
|
||||
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
base.common_check_version("socketio", "1", clean)
|
||||
os.chdir(old_cur)
|
||||
|
||||
if not base.is_dir(base_dir + "/socket.io-client-cpp"):
|
||||
base.cmd_in_dir(base_dir, "git", ["clone", "https://github.com/socketio/socket.io-client-cpp.git"])
|
||||
base.cmd_in_dir(base_dir + "/socket.io-client-cpp", "git", ["checkout", "da779141a7379cc30c870d48295033bc16a23c66"])
|
||||
@ -37,6 +48,7 @@ def make():
|
||||
base.apply_patch(base_dir + "/socket.io-client-cpp/src/internal/sio_client_impl.cpp", base_dir + "/patches/sio_client_impl_fail.patch")
|
||||
base.apply_patch(base_dir + "/socket.io-client-cpp/src/internal/sio_client_impl.cpp", base_dir + "/patches/sio_client_impl_open.patch")
|
||||
base.apply_patch(base_dir + "/socket.io-client-cpp/src/internal/sio_client_impl.cpp", base_dir + "/patches/sio_client_impl_close_timeout.patch")
|
||||
base.apply_patch(base_dir + "/socket.io-client-cpp/src/internal/sio_client_impl.cpp", base_dir + "/patches/sio_client_impl_encode.patch")
|
||||
|
||||
# no tls realization (remove if socket.io fix this)
|
||||
dst_dir = base_dir + "/socket.io-client-cpp/src_no_tls"
|
||||
|
||||
@ -10,10 +10,10 @@ import v8_89
|
||||
|
||||
def clean():
|
||||
if base.is_dir("depot_tools"):
|
||||
base.delete_dir_with_access_error("depot_tools");
|
||||
base.delete_dir_with_access_error("depot_tools")
|
||||
base.delete_dir("depot_tools")
|
||||
if base.is_dir("v8"):
|
||||
base.delete_dir_with_access_error("v8");
|
||||
base.delete_dir_with_access_error("v8")
|
||||
base.delete_dir("v8")
|
||||
if base.is_exist("./.gclient"):
|
||||
base.delete_file("./.gclient")
|
||||
@ -26,6 +26,8 @@ def clean():
|
||||
def is_main_platform():
|
||||
if (config.check_option("platform", "win_64") or config.check_option("platform", "win_32")):
|
||||
return True
|
||||
if (config.check_option("platform", "win_arm64")):
|
||||
return True
|
||||
if (config.check_option("platform", "linux_64") or config.check_option("platform", "linux_32") or config.check_option("platform", "linux_arm64")):
|
||||
return True
|
||||
if config.check_option("platform", "mac_64"):
|
||||
@ -45,7 +47,7 @@ def is_use_clang():
|
||||
gcc_version = base.get_gcc_version()
|
||||
|
||||
is_clang = "false"
|
||||
if (gcc_version >= 6000):
|
||||
if config.option("sysroot") == "" and (gcc_version >= 6000 or "1" == config.option("use-clang")):
|
||||
is_clang = "true"
|
||||
|
||||
print("gcc version: " + str(gcc_version) + ", use clang:" + is_clang)
|
||||
@ -119,7 +121,7 @@ def make():
|
||||
# windows hack (delete later) ----------------------
|
||||
if ("windows" == base.host_platform()):
|
||||
base.delete_dir_with_access_error("v8/buildtools/win")
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"], True)
|
||||
base.cmd("gclient", ["sync", "--force"], True)
|
||||
else:
|
||||
base.cmd("gclient", ["sync"], True)
|
||||
@ -233,8 +235,7 @@ def make_xp():
|
||||
base.replaceInFile("depot_tools/cipd.ps1", "windows-386", "windows-amd64")
|
||||
|
||||
# old variant
|
||||
#path_to_python2 = "/depot_tools/win_tools-2_7_13_chromium7_bin/python/bin"
|
||||
path_to_python2 = "/depot_tools/bootstrap-2@3_8_10_chromium_23_bin/python/bin"
|
||||
path_to_python2 = "/depot_tools/bootstrap-2@3_11_8_chromium_35_bin/python/bin"
|
||||
os.environ["PATH"] = os.pathsep.join([base_dir + "/depot_tools",
|
||||
base_dir + path_to_python2,
|
||||
config.option("vs-path") + "/../Common7/IDE",
|
||||
@ -246,7 +247,7 @@ def make_xp():
|
||||
base.cmd("./depot_tools/fetch", ["v8"], True)
|
||||
base.cmd("./depot_tools/gclient", ["sync", "-r", "4.10.253"], True)
|
||||
base.delete_dir_with_access_error("v8/buildtools/win")
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"], True)
|
||||
base.cmd("gclient", ["sync", "--force"], True)
|
||||
|
||||
# save common py script
|
||||
@ -269,7 +270,7 @@ def make_xp():
|
||||
"for file in projects:",
|
||||
" replaceInFile(file, '<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>', '<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>')",
|
||||
" replaceInFile(file, '<RuntimeLibrary>MultiThreaded</RuntimeLibrary>', '<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>')",
|
||||
]);
|
||||
])
|
||||
|
||||
programFilesDir = base.get_env("ProgramFiles")
|
||||
if ("" != base.get_env("ProgramFiles(x86)")):
|
||||
|
||||
@ -7,6 +7,25 @@ import base
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def clean():
|
||||
if base.is_dir("depot_tools"):
|
||||
base.delete_dir_with_access_error("depot_tools")
|
||||
base.delete_dir("depot_tools")
|
||||
if base.is_dir("v8"):
|
||||
base.delete_dir_with_access_error("v8")
|
||||
base.delete_dir("v8")
|
||||
if base.is_exist("./.gclient"):
|
||||
base.delete_file("./.gclient")
|
||||
if base.is_exist("./.gclient_entries"):
|
||||
base.delete_file("./.gclient_entries")
|
||||
if base.is_exist("./.gclient_previous_sync_commits"):
|
||||
base.delete_file("./.gclient_previous_sync_commits")
|
||||
if base.is_exist("./.gcs_entries"):
|
||||
base.delete_file("./.gcs_entries")
|
||||
if base.is_exist("./.cipd"):
|
||||
base.delete_dir("./.cipd")
|
||||
return
|
||||
|
||||
def change_bootstrap():
|
||||
base.move_file("./depot_tools/bootstrap/manifest.txt", "./depot_tools/bootstrap/manifest.txt.bak")
|
||||
content = "# changed by build_tools\n\n"
|
||||
@ -16,11 +35,21 @@ def change_bootstrap():
|
||||
content += "infra/3pp/tools/cpython/${platform} version:2@2.7.18.chromium.39\n\n"
|
||||
|
||||
content += "@Subdir python3\n"
|
||||
content += "infra/3pp/tools/cpython3/${platform} version:2@3.8.10.chromium.23\n\n"
|
||||
|
||||
if ("windows" == base.host_platform()):
|
||||
content += "infra/3pp/tools/cpython3/${platform} version:2@3.11.8.chromium.35\n\n"
|
||||
else:
|
||||
content += "infra/3pp/tools/cpython3/${platform} version:2@3.8.10.chromium.23\n\n"
|
||||
|
||||
content += "@Subdir git\n"
|
||||
content += "infra/3pp/tools/git/${platform} version:2@2.41.0.chromium.11\n"
|
||||
|
||||
base.replaceInFile("./depot_tools/bootstrap/bootstrap.py",
|
||||
"raise subprocess.CalledProcessError(proc.returncode, argv, None)", "return")
|
||||
|
||||
base.replaceInFile("./depot_tools/bootstrap/bootstrap.py",
|
||||
" _win_git_bootstrap_config()", " #_win_git_bootstrap_config()")
|
||||
|
||||
base.writeFile("./depot_tools/bootstrap/manifest.txt", content)
|
||||
return
|
||||
|
||||
@ -38,7 +67,13 @@ def make_args(args, platform, is_64=True, is_debug=False):
|
||||
args_copy.append("target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("v8_target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("use_sysroot=true")
|
||||
|
||||
|
||||
if (platform == "win_arm64"):
|
||||
args_copy = args[:]
|
||||
args_copy.append("target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("v8_target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("is_clang=false")
|
||||
|
||||
if is_debug:
|
||||
args_copy.append("is_debug=true")
|
||||
if (platform == "windows"):
|
||||
@ -46,20 +81,45 @@ def make_args(args, platform, is_64=True, is_debug=False):
|
||||
else:
|
||||
args_copy.append("is_debug=false")
|
||||
|
||||
if (platform == "linux"):
|
||||
args_copy.append("is_clang=true")
|
||||
args_copy.append("use_sysroot=false")
|
||||
linux_clang = False
|
||||
if platform == "linux":
|
||||
if "" != config.option("sysroot"):
|
||||
args_copy.append("use_sysroot=false")
|
||||
args_copy.append("is_clang=false")
|
||||
else:
|
||||
args_copy.append("is_clang=true")
|
||||
if "1" == config.option("use-clang"):
|
||||
linux_clang = True
|
||||
else:
|
||||
args_copy.append("use_sysroot=false")
|
||||
|
||||
|
||||
if (platform == "windows"):
|
||||
args_copy.append("is_clang=false")
|
||||
|
||||
if (platform == "mac") and base.is_os_arm():
|
||||
args_copy.append("host_cpu=\\\"x64\\\"")
|
||||
|
||||
if linux_clang != True:
|
||||
args_copy.append("use_custom_libcxx=false")
|
||||
|
||||
return "--args=\"" + " ".join(args_copy) + "\""
|
||||
|
||||
def ninja_windows_make(args, is_64=True, is_debug=False):
|
||||
def ninja_windows_make(args, is_64=True, is_debug=False, is_arm=False):
|
||||
directory_out = "out.gn/"
|
||||
directory_out += ("win_64/" if is_64 else "win_32/")
|
||||
|
||||
if is_arm:
|
||||
directory_out += "win_arm64/"
|
||||
else:
|
||||
directory_out += ("win_64/" if is_64 else "win_32/")
|
||||
|
||||
directory_out += ("debug" if is_debug else "release")
|
||||
|
||||
base.cmd2("gn", ["gen", directory_out, make_args(args, "windows", is_64, is_debug)])
|
||||
if is_arm:
|
||||
base.cmd2("gn", ["gen", directory_out, make_args(args, "win_arm64", is_64, is_debug)])
|
||||
else:
|
||||
base.cmd2("gn", ["gen", directory_out, make_args(args, "windows", is_64, is_debug)])
|
||||
|
||||
base.copy_file("./" + directory_out + "/obj/v8_wrappers.ninja", "./" + directory_out + "/obj/v8_wrappers.ninja.bak")
|
||||
base.replaceInFile("./" + directory_out + "/obj/v8_wrappers.ninja", "target_output_name = v8_wrappers", "target_output_name = v8_wrappers\nbuild obj/v8_wrappers.obj: cxx ../../../src/base/platform/wrappers.cc")
|
||||
base.replaceInFile("./" + directory_out + "/obj/v8_wrappers.ninja", "build obj/v8_wrappers.lib: alink", "build obj/v8_wrappers.lib: alink obj/v8_wrappers.obj")
|
||||
@ -69,7 +129,10 @@ def ninja_windows_make(args, is_64=True, is_debug=False):
|
||||
if (-1 == win_toolset_wrapper_file_content.find("line = line.decode('utf8')")):
|
||||
base.replaceInFile(win_toolset_wrapper_file, "for line in link.stdout:\n", "for line in link.stdout:\n line = line.decode('utf8')\n")
|
||||
|
||||
|
||||
base.cmd("ninja", ["-C", directory_out, "v8_wrappers"])
|
||||
if is_arm:
|
||||
base.copy_file('./' + directory_out + '/obj/v8_wrappers.lib', './' + directory_out + '/x64/obj/v8_wrappers.lib')
|
||||
base.cmd("ninja", ["-C", directory_out])
|
||||
base.delete_file("./" + directory_out + "/obj/v8_wrappers.ninja")
|
||||
base.move_file("./" + directory_out + "/obj/v8_wrappers.ninja.bak", "./" + directory_out + "/obj/v8_wrappers.ninja")
|
||||
@ -105,6 +168,11 @@ def make():
|
||||
if not base.is_dir(base_dir):
|
||||
base.create_dir(base_dir)
|
||||
|
||||
base.common_check_version("v8", "1", clean)
|
||||
|
||||
if ("mac" == base.host_platform()):
|
||||
base.cmd("git", ["config", "--global", "http.postBuffer", "157286400"], True)
|
||||
|
||||
os.chdir(base_dir)
|
||||
if not base.is_dir("depot_tools"):
|
||||
base.cmd("git", ["clone", "https://chromium.googlesource.com/chromium/tools/depot_tools.git"])
|
||||
@ -121,7 +189,7 @@ def make():
|
||||
base.copy_dir("./v8/third_party", "./v8/third_party_new")
|
||||
if ("windows" == base.host_platform()):
|
||||
os.chdir("v8")
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
|
||||
base.cmd("git", ["config", "--system", "core.longpaths", "true"], True)
|
||||
os.chdir("../")
|
||||
v8_branch_version = "remotes/branch-heads/8.9"
|
||||
if ("mac" == base.host_platform()):
|
||||
@ -132,11 +200,27 @@ def make():
|
||||
|
||||
if ("windows" == base.host_platform()):
|
||||
base.replaceInFile("v8/build/config/win/BUILD.gn", ":static_crt", ":dynamic_crt")
|
||||
|
||||
# fix for new depot_tools and vs2019, as VC folder contains a folder with a symbol in the name
|
||||
# sorting is done by increasing version, so 0 is a dummy value
|
||||
replace_src = " def to_int_if_int(x):\n try:\n return int(x)\n except ValueError:\n return x"
|
||||
replace_dst = " def to_int_if_int(x):\n try:\n return int(x)\n except ValueError:\n return 0"
|
||||
base.replaceInFile("v8/build/vs_toolchain.py", replace_src, replace_dst)
|
||||
|
||||
|
||||
if not base.is_file("v8/src/base/platform/wrappers.cc"):
|
||||
base.writeFile("v8/src/base/platform/wrappers.cc", "#include \"src/base/platform/wrappers.h\"\n")
|
||||
|
||||
if config.check_option("platform", "win_arm64"):
|
||||
base.replaceInFile("v8/build/toolchain/win/setup_toolchain.py", "SDK_VERSION = \'10.0.26100.0\'", "SDK_VERSION = \'10.0.22621.0\'")
|
||||
else:
|
||||
base.replaceInFile("depot_tools/gclient_paths.py", "@functools.lru_cache", "")
|
||||
|
||||
if ("mac" == base.host_platform()):
|
||||
if not base.is_file("v8/build/config/compiler/BUILD.gn.bak"):
|
||||
base.copy_file("v8/build/config/compiler/BUILD.gn", "v8/build/config/compiler/BUILD.gn.bak")
|
||||
base.replaceInFile("v8/build/config/compiler/BUILD.gn", "\"-Wloop-analysis\",", "\"-Wloop-analysis\", \"-D_Float16=short\",")
|
||||
|
||||
if not base.is_file("v8/third_party/jinja2/tests.py.bak"):
|
||||
base.copy_file("v8/third_party/jinja2/tests.py", "v8/third_party/jinja2/tests.py.bak")
|
||||
base.replaceInFile("v8/third_party/jinja2/tests.py", "from collections import Mapping", "try:\n from collections.abc import Mapping\nexcept ImportError:\n from collections import Mapping")
|
||||
@ -147,12 +231,27 @@ def make():
|
||||
"is_component_build=false",
|
||||
"v8_monolithic=true",
|
||||
"v8_use_external_startup_data=false",
|
||||
"use_custom_libcxx=false",
|
||||
"treat_warnings_as_errors=false"]
|
||||
|
||||
if config.check_option("platform", "linux_64"):
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_64", make_args(gn_args, "linux")])
|
||||
base.cmd("ninja", ["-C", "out.gn/linux_64"])
|
||||
if config.option("sysroot") != "":
|
||||
src_replace = "config(\"compiler\") {\n asmflags = []\n cflags = []\n cflags_c = []\n cflags_cc = []\n cflags_objc = []\n cflags_objcc = []\n ldflags = []"
|
||||
dst_replace = "config(\"compiler\") {\n asmflags = []\n cflags = [\"--sysroot=" + config.option("sysroot") + "\"]" + "\n cflags_c = []\n cflags_cc = [\"--sysroot=" + config.option("sysroot") + "\"]" + "\n cflags_objc = []\n cflags_objcc = []\n ldflags = [\"--sysroot=" + config.option("sysroot") + "\"]"
|
||||
base.replaceInFile("build/config/compiler/BUILD.gn", src_replace, dst_replace)
|
||||
|
||||
src_replace = "gcc_toolchain(\"x64\") {\n cc = \"gcc\"\n cxx = \"g++\""
|
||||
dst_replace = "gcc_toolchain(\"x64\") {\n cc = \""+ config.get_custom_sysroot_bin() + "/gcc\"\n cxx = \"" + config.get_custom_sysroot_bin() + "/g++\""
|
||||
base.replaceInFile("build/toolchain/linux/BUILD.gn", src_replace, dst_replace)
|
||||
|
||||
old_env = dict(os.environ)
|
||||
base.set_sysroot_env()
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_64", make_args(gn_args, "linux")], False)
|
||||
base.cmd2("ninja", ["-C", "out.gn/linux_64"], False)
|
||||
base.restore_sysroot_env()
|
||||
else:
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_64", make_args(gn_args, "linux")], False)
|
||||
base.cmd2("ninja", ["-C", "out.gn/linux_64"], False)
|
||||
|
||||
|
||||
if config.check_option("platform", "linux_32"):
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_32", make_args(gn_args, "linux", False)])
|
||||
@ -166,6 +265,9 @@ def make():
|
||||
if config.check_option("platform", "mac_64"):
|
||||
base.cmd2("gn", ["gen", "out.gn/mac_64", make_args(gn_args, "mac")])
|
||||
base.cmd("ninja", ["-C", "out.gn/mac_64"])
|
||||
|
||||
if config.check_option("platform", "win_arm64") and not base.is_file("out.gn/win_arm64/release/obj/v8_monolith.lib"):
|
||||
ninja_windows_make(gn_args, True, False, True)
|
||||
|
||||
if config.check_option("platform", "win_64"):
|
||||
if (-1 != config.option("config").lower().find("debug")):
|
||||
|
||||
@ -22,4 +22,6 @@ def make():
|
||||
deploy_mobile.make()
|
||||
if config.check_option("module", "osign"):
|
||||
deploy_osign.make()
|
||||
if base.is_use_create_artifacts_qemu_any_platform():
|
||||
base.create_artifacts_qemu_any_platform()
|
||||
return
|
||||
|
||||
@ -15,6 +15,7 @@ def make():
|
||||
continue
|
||||
|
||||
root_dir = base_dir + ("/" + native_platform + "/" + branding + ("/DocumentBuilder" if base.is_windows() else "/documentbuilder"))
|
||||
root_dir_win64 = base_dir + "/win_64/" + branding + "/DocumentBuilder"
|
||||
if (base.is_dir(root_dir)):
|
||||
base.delete_dir(root_dir)
|
||||
base.create_dir(root_dir)
|
||||
@ -39,10 +40,12 @@ def make():
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "PdfFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "DjVuFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "XpsFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "OFDFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HtmlFile2")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HtmlRenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "Fb2File")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "EpubFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "IWorkFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HWPFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "DocxRenderer")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", root_dir + "/cmap.bin")
|
||||
|
||||
@ -55,17 +58,7 @@ def make():
|
||||
# base.generate_check_linux_system(git_dir + "/build_tools", root_dir)
|
||||
|
||||
# icu
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icudt58.dll", root_dir + "/icudt58.dll")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icuuc58.dll", root_dir + "/icuuc58.dll")
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.so.58", root_dir + "/libicudata.so.58")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.so.58", root_dir + "/libicuuc.so.58")
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.58.dylib", root_dir + "/libicudata.58.dylib")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.58.dylib", root_dir + "/libicuuc.58.dylib")
|
||||
base.deploy_icu(core_dir, root_dir, native_platform)
|
||||
|
||||
# doctrenderer
|
||||
if isWindowsXP:
|
||||
@ -76,9 +69,12 @@ def make():
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_build_dir + "/lib/" + platform_postfix + "/doctrenderer.lib", root_dir + "/doctrenderer.lib")
|
||||
base.copy_v8_files(core_dir, root_dir, platform, isWindowsXP)
|
||||
# python wrapper
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "docbuilder.c")
|
||||
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder.py", root_dir + "/docbuilder.py")
|
||||
# java wrapper
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "docbuilder.jni")
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.java/build/libs/docbuilder.jar", root_dir + "/docbuilder.jar")
|
||||
|
||||
# app
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, root_dir, "docbuilder")
|
||||
@ -101,25 +97,51 @@ def make():
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.com/src/docbuilder_midl.h", root_dir + "/include/docbuilder_midl.h")
|
||||
base.replaceInFile(root_dir + "/include/docbuilder.h", "Q_DECL_EXPORT", "BUILDING_DOCBUILDER")
|
||||
|
||||
|
||||
if ("win_64" == platform):
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.com/deploy/win_64/docbuilder.com.dll", root_dir + "/docbuilder.com.dll")
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.net/deploy/win_64/docbuilder.net.dll", root_dir + "/docbuilder.net.dll")
|
||||
|
||||
|
||||
elif ("win_32" == platform):
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.com/deploy/win_32/docbuilder.com.dll", root_dir + "/docbuilder.com.dll")
|
||||
base.copy_file(core_dir + "/DesktopEditor/doctrenderer/docbuilder.net/deploy/win_32/docbuilder.net.dll", root_dir + "/docbuilder.net.dll")
|
||||
|
||||
# correct ios frameworks
|
||||
if ("ios" == platform):
|
||||
base.generate_plist(root_dir)
|
||||
base.for_each_framework(root_dir, "ios", callbacks=[base.generate_plist, base.generate_xcprivacy])
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
base.linux_correct_rpath_docbuilder(root_dir)
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.for_each_framework(root_dir, "mac", callbacks=[base.generate_plist], max_depth=1)
|
||||
base.mac_correct_rpath_x2t(root_dir)
|
||||
base.mac_correct_rpath_docbuilder(root_dir)
|
||||
|
||||
return
|
||||
|
||||
base.create_x2t_js_cache(root_dir, "builder", platform)
|
||||
|
||||
base.create_dir(root_dir + "/fonts")
|
||||
base.copy_dir(git_dir + "/core-fonts/asana", root_dir + "/fonts/asana")
|
||||
base.copy_dir(git_dir + "/core-fonts/caladea", root_dir + "/fonts/caladea")
|
||||
base.copy_dir(git_dir + "/core-fonts/crosextra", root_dir + "/fonts/crosextra")
|
||||
base.copy_dir(git_dir + "/core-fonts/openoffice", root_dir + "/fonts/openoffice")
|
||||
base.copy_file(git_dir + "/core-fonts/ASC.ttf", root_dir + "/fonts/ASC.ttf")
|
||||
|
||||
# delete unnecessary builder files
|
||||
def delete_files(files):
|
||||
for file in files:
|
||||
base.delete_file(file)
|
||||
|
||||
delete_files(base.find_files(root_dir, "*.wasm"))
|
||||
delete_files(base.find_files(root_dir, "*_ie.js"))
|
||||
base.delete_file(root_dir + "/sdkjs/pdf/src/engine/cmap.bin")
|
||||
if 0 != platform.find("mac"):
|
||||
delete_files(base.find_files(root_dir, "sdk-all.js"))
|
||||
delete_files(base.find_files(root_dir, "sdk-all-min.js"))
|
||||
base.delete_dir(root_dir + "/sdkjs/slide/themes")
|
||||
base.delete_dir(root_dir + "/sdkjs/cell/css")
|
||||
base.delete_file(root_dir + "/sdkjs/pdf/src/engine/viewer.js")
|
||||
base.delete_file(root_dir + "/sdkjs/common/spell/spell/spell.js.mem")
|
||||
base.delete_dir(root_dir + "/sdkjs/common/Images")
|
||||
|
||||
return
|
||||
|
||||
@ -30,15 +30,18 @@ def make():
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "kernel_network")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "graphics")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "doctrenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "HtmlRenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "DjVuFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "XpsFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "OFDFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "PdfFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "HtmlFile2")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "UnicodeConverter")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "Fb2File")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "EpubFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "IWorkFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "HWPFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "DocxRenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "hunspell")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", archive_dir + "/cmap.bin")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "x2t")
|
||||
|
||||
@ -50,7 +53,8 @@ def make():
|
||||
if ("windows" == base.host_platform()):
|
||||
base.copy_files(core_dir + "/Common/3dParty/icu/" + platform + "/build/*.dll", archive_dir + "/")
|
||||
else:
|
||||
base.copy_files(core_dir + "/Common/3dParty/icu/" + platform + "/build/*", archive_dir + "/")
|
||||
if not (0 == platform.find("mac") and config.check_option("config", "bundle_dylibs")):
|
||||
base.copy_files(core_dir + "/Common/3dParty/icu/" + platform + "/build/*", archive_dir + "/")
|
||||
base.copy_v8_files(core_dir, archive_dir, platform)
|
||||
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "allfontsgen")
|
||||
@ -61,13 +65,18 @@ def make():
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "ooxml_crypt")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "vboxtester")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "metafiletester")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "dictionariestester")
|
||||
|
||||
# correct mac frameworks
|
||||
if (0 == platform.find("mac")):
|
||||
base.for_each_framework(archive_dir, "mac", callbacks=[base.generate_plist], max_depth=1)
|
||||
base.mac_correct_rpath_x2t(archive_dir)
|
||||
|
||||
# js cache
|
||||
base.generate_doctrenderer_config(archive_dir + "/DoctRenderer.config", "./", "builder", "", "./dictionaries")
|
||||
base.create_x2t_js_cache(archive_dir, "core", platform)
|
||||
base.delete_file(archive_dir + "/DoctRenderer.config")
|
||||
|
||||
# dictionaries
|
||||
base.copy_dictionaries(git_dir + "/dictionaries", archive_dir + "/dictionaries", True, False)
|
||||
|
||||
if base.is_file(archive_dir + ".7z"):
|
||||
base.delete_file(archive_dir + ".7z")
|
||||
base.archive_folder(archive_dir + "/*", archive_dir + ".7z")
|
||||
|
||||
return
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ def copy_lib_with_links(src_dir, dst_dir, lib, version):
|
||||
lib_major_name = lib + "." + major_version
|
||||
|
||||
base.copy_file(src_dir + "/" + lib_full_name, dst_dir + "/" + lib_full_name)
|
||||
|
||||
|
||||
base.cmd_in_dir(dst_dir, "ln", ["-s", "./" + lib_full_name, "./" + lib_major_name])
|
||||
base.cmd_in_dir(dst_dir, "ln", ["-s", "./" + lib_major_name, "./" + lib])
|
||||
|
||||
@ -40,7 +40,7 @@ def make():
|
||||
isWindowsXP = False if (-1 == native_platform.find("_xp")) else True
|
||||
platform = native_platform[0:-3] if isWindowsXP else native_platform
|
||||
|
||||
apps_postfix = "build" + base.qt_dst_postfix();
|
||||
apps_postfix = "build" + base.qt_dst_postfix()
|
||||
if ("" != config.option("branding")):
|
||||
apps_postfix += ("/" + config.option("branding"))
|
||||
apps_postfix += "/"
|
||||
@ -65,12 +65,14 @@ def make():
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "PdfFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "DjVuFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "XpsFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "OFDFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "HtmlFile2")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "HtmlRenderer")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "Fb2File")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "EpubFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "IWorkFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "HWPFile")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "DocxRenderer")
|
||||
|
||||
|
||||
if ("ios" == platform):
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "x2t")
|
||||
else:
|
||||
@ -80,28 +82,18 @@ def make():
|
||||
# base.generate_check_linux_system(git_dir + "/build_tools", root_dir + "/converter")
|
||||
|
||||
# icu
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icudt58.dll", root_dir + "/converter/icudt58.dll")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icuuc58.dll", root_dir + "/converter/icuuc58.dll")
|
||||
#base.copy_file(git_dir + "/desktop-apps/common/converter/package.config", root_dir + "/converter/package.config")
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.so.58", root_dir + "/converter/libicudata.so.58")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.so.58", root_dir + "/converter/libicuuc.so.58")
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.58.dylib", root_dir + "/converter/libicudata.58.dylib")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.58.dylib", root_dir + "/converter/libicuuc.58.dylib")
|
||||
base.deploy_icu(core_dir, root_dir + "/converter", native_platform)
|
||||
|
||||
# doctrenderer
|
||||
if isWindowsXP:
|
||||
base.copy_lib(build_libraries_path + "/xp", root_dir + "/converter", "doctrenderer")
|
||||
else:
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "doctrenderer")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "doctrenderer")
|
||||
base.copy_v8_files(core_dir, root_dir + "/converter", platform, isWindowsXP)
|
||||
|
||||
base.generate_doctrenderer_config(root_dir + "/converter/DoctRenderer.config", "../editors/", "desktop", "", "../dictionaries")
|
||||
base.copy_dir(git_dir + "/document-templates/new", root_dir + "/converter/empty")
|
||||
base.copy_dir(git_dir + "/desktop-apps/common/templates", root_dir + "/converter/templates")
|
||||
|
||||
# dictionaries
|
||||
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries")
|
||||
@ -113,8 +105,6 @@ def make():
|
||||
base.copy_dir(git_dir + "/core-fonts/openoffice", root_dir + "/fonts/openoffice")
|
||||
base.copy_file(git_dir + "/core-fonts/ASC.ttf", root_dir + "/fonts/ASC.ttf")
|
||||
|
||||
base.copy_file(git_dir + "/desktop-apps/common/package/license/3dparty/3DPARTYLICENSE", root_dir + "/3DPARTYLICENSE")
|
||||
|
||||
# cef
|
||||
build_dir_name = "build"
|
||||
if (0 == platform.find("linux")) and (config.check_option("config", "cef_version_107")):
|
||||
@ -127,6 +117,20 @@ def make():
|
||||
else:
|
||||
base.copy_files(core_dir + "/Common/3dParty/cef/" + native_platform + "/" + build_dir_name + "/*", root_dir)
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
dir_base_old = os.getcwd()
|
||||
os.chdir(root_dir + "/Chromium Embedded Framework.framework")
|
||||
base.create_dir("Versions")
|
||||
base.create_dir("Versions/A")
|
||||
base.move_file("Chromium Embedded Framework", "Versions/A/Chromium Embedded Framework")
|
||||
base.move_dir("Resources", "Versions/A/Resources")
|
||||
base.move_dir("Libraries", "Versions/A/Libraries")
|
||||
base.cmd("ln", ["-s", "Versions/A/Chromium Embedded Framework", "Chromium Embedded Framework"])
|
||||
base.cmd("ln", ["-s", "Versions/A/Resources", "Resources"])
|
||||
base.cmd("ln", ["-s", "Versions/A/Libraries", "Libraries"])
|
||||
base.cmd("ln", ["-s", "A", "Versions/Current"])
|
||||
os.chdir(dir_base_old);
|
||||
|
||||
isUseQt = True
|
||||
if (0 == platform.find("mac")) or (0 == platform.find("ios")):
|
||||
isUseQt = False
|
||||
@ -137,18 +141,18 @@ def make():
|
||||
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "ascdocumentscore")
|
||||
if (0 != platform.find("mac")):
|
||||
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "qtascdocumentscore")
|
||||
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.copy_dir(core_build_dir + "/bin/" + platform_postfix + "/editors_helper.app", root_dir + "/editors_helper.app")
|
||||
else:
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix + ("/xp" if isWindowsXP else ""), root_dir, "editors_helper")
|
||||
|
||||
|
||||
if isUseQt:
|
||||
base.qt_copy_lib("Qt5Core", root_dir)
|
||||
base.qt_copy_lib("Qt5Gui", root_dir)
|
||||
base.qt_copy_lib("Qt5PrintSupport", root_dir)
|
||||
base.qt_copy_lib("Qt5Svg", root_dir)
|
||||
base.qt_copy_lib("Qt5Widgets", root_dir)
|
||||
base.qt_copy_lib("Qt5Widgets", root_dir)
|
||||
base.qt_copy_lib("Qt5Network", root_dir)
|
||||
base.qt_copy_lib("Qt5OpenGL", root_dir)
|
||||
|
||||
@ -157,7 +161,7 @@ def make():
|
||||
base.qt_copy_plugin("imageformats", root_dir)
|
||||
base.qt_copy_plugin("platforms", root_dir)
|
||||
base.qt_copy_plugin("platforminputcontexts", root_dir)
|
||||
base.qt_copy_plugin("printsupport", root_dir)
|
||||
base.qt_copy_plugin("printsupport", root_dir)
|
||||
|
||||
base.qt_copy_plugin("platformthemes", root_dir)
|
||||
base.qt_copy_plugin("xcbglintegrations", root_dir)
|
||||
@ -182,6 +186,8 @@ def make():
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/projicons/" + apps_postfix + "/projicons.exe", root_dir + "/DesktopEditors.exe")
|
||||
if not isWindowsXP:
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/update-daemon/" + apps_postfix + "/updatesvc.exe", root_dir + "/updatesvc.exe")
|
||||
else:
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/online-installer/" + apps_postfix + "/online-installer.exe", root_dir + "/online-installer.exe")
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/" + apps_postfix + "/DesktopEditors.exe", root_dir + "/editors.exe")
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/res/icons/desktopeditors.ico", root_dir + "/app.ico")
|
||||
elif (0 == platform.find("linux")):
|
||||
@ -189,9 +195,9 @@ def make():
|
||||
|
||||
if base.check_congig_option_with_platfom(platform, "libvlc"):
|
||||
vlc_dir = git_dir + "/core/Common/3dParty/libvlc/build/" + platform + "/lib"
|
||||
|
||||
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_dir(vlc_dir + "/plugins", root_dir + "/plugins")
|
||||
base.copy_dir(vlc_dir + "/plugins", root_dir + "/plugins")
|
||||
base.copy_files(vlc_dir + "/*.dll", root_dir)
|
||||
base.copy_file(vlc_dir + "/vlc-cache-gen.exe", root_dir + "/vlc-cache-gen.exe")
|
||||
elif (0 == platform.find("linux")):
|
||||
@ -213,8 +219,6 @@ def make():
|
||||
|
||||
base.create_dir(root_dir + "/editors")
|
||||
base.copy_dir(base_dir + "/js/" + branding + "/desktop/sdkjs", root_dir + "/editors/sdkjs")
|
||||
if len(os.listdir(root_dir + "/editors/sdkjs")) == 0:
|
||||
base.delete_dir(root_dir + "/editors/sdkjs") # delete empty folder. for bug 62528
|
||||
base.copy_dir(base_dir + "/js/" + branding + "/desktop/web-apps", root_dir + "/editors/web-apps")
|
||||
for file in glob.glob(root_dir + "/editors/web-apps/apps/*/*/*.js.map"):
|
||||
base.delete_file(file)
|
||||
@ -239,7 +243,22 @@ def make():
|
||||
#base.copy_dir(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins/encrypt/ui/common/{14A8FC87-8E26-4216-B34E-F27F053B2EC4}", root_dir + "/editors/sdkjs-plugins/{14A8FC87-8E26-4216-B34E-F27F053B2EC4}")
|
||||
#base.copy_dir(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins/encrypt/ui/engine/database/{9AB4BBA8-A7E5-48D5-B683-ECE76A020BB1}", root_dir + "/editors/sdkjs-plugins/{9AB4BBA8-A7E5-48D5-B683-ECE76A020BB1}")
|
||||
base.copy_sdkjs_plugin(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins", root_dir + "/editors/sdkjs-plugins", "sendto", True)
|
||||
|
||||
|
||||
isUseAgent = True
|
||||
if isWindowsXP:
|
||||
isUseAgent = False
|
||||
if (0 == platform.find("mac")) and (config.check_option("config", "use_v8")):
|
||||
isUseAgent = False
|
||||
|
||||
if (isUseAgent):
|
||||
agent_plugin_dir = git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins/ai-agent"
|
||||
if (False):
|
||||
base.cmd_in_dir(agent_plugin_dir, "npm", ["install"], True)
|
||||
base.cmd_in_dir(agent_plugin_dir, "npm", ["run", "build"], True)
|
||||
base.copy_dir(agent_plugin_dir + "/{9DC93CDB-B576-4F0C-B55E-FCC9C48DD777}", root_dir + "/editors/sdkjs-plugins/{9DC93CDB-B576-4F0C-B55E-FCC9C48DD777}")
|
||||
else:
|
||||
base.copy_dir(agent_plugin_dir + "/deploy/{9DC93CDB-B576-4F0C-B55E-FCC9C48DD777}", root_dir + "/editors/sdkjs-plugins/{9DC93CDB-B576-4F0C-B55E-FCC9C48DD777}")
|
||||
|
||||
base.copy_file(base_dir + "/js/" + branding + "/desktop/index.html", root_dir + "/index.html")
|
||||
base.create_dir(root_dir + "/editors/webext")
|
||||
base.copy_file(base_dir + "/js/" + branding + "/desktop/noconnect.html", root_dir + "/editors/webext/noconnect.html")
|
||||
@ -252,7 +271,10 @@ def make():
|
||||
|
||||
isUseJSC = False
|
||||
if (0 == platform.find("mac")):
|
||||
file_size_doctrenderer = os.path.getsize(root_dir + "/converter/libdoctrenderer.dylib")
|
||||
doctrenderer_lib = "libdoctrenderer.dylib"
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
doctrenderer_lib = "doctrenderer.framework/doctrenderer"
|
||||
file_size_doctrenderer = os.path.getsize(root_dir + "/converter/" + doctrenderer_lib)
|
||||
print("file_size_doctrenderer: " + str(file_size_doctrenderer))
|
||||
if (file_size_doctrenderer < 5*1024*1024):
|
||||
isUseJSC = True
|
||||
@ -260,42 +282,52 @@ def make():
|
||||
if isUseJSC:
|
||||
base.delete_file(root_dir + "/converter/icudtl.dat")
|
||||
|
||||
base.create_x2t_js_cache(root_dir + "/converter", "desktop", platform)
|
||||
|
||||
if (0 == platform.find("win")):
|
||||
base.delete_file(root_dir + "/cef_sandbox.lib")
|
||||
base.delete_file(root_dir + "/libcef.lib")
|
||||
|
||||
isMacArmPlaformOnIntel = False
|
||||
is_host_not_arm = False
|
||||
host_platform = ""
|
||||
|
||||
# TODO: fix this on mac_arm64 (qemu)
|
||||
# on windows we are using qemu
|
||||
if (platform == "mac_arm64") and not base.is_os_arm():
|
||||
isMacArmPlaformOnIntel = True
|
||||
is_host_not_arm = True
|
||||
host_platform = "mac_64"
|
||||
|
||||
# all themes generate ----
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, root_dir + "/converter", "allfontsgen")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, root_dir + "/converter", "allthemesgen")
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
# gen plists with max_depth 2 because frameworks are only located in root_dir and converter subdirectory
|
||||
base.for_each_framework(root_dir, "mac", callbacks=[base.generate_plist], max_depth=2)
|
||||
base.mac_correct_rpath_desktop(root_dir)
|
||||
|
||||
if isMacArmPlaformOnIntel:
|
||||
if is_host_not_arm:
|
||||
sdkjs_dir = root_dir + "/editors/sdkjs"
|
||||
end_find_platform = sdkjs_dir.rfind("/mac_arm64/")
|
||||
sdkjs_dir_mac64 = sdkjs_dir[0:end_find_platform] + "/mac_64/" + sdkjs_dir[end_find_platform+11:]
|
||||
str1 = "/" + platform + "/"
|
||||
str2 = "/" + host_platform + "/"
|
||||
sdkjs_dir_host = sdkjs_dir.replace(str1, str2)
|
||||
base.delete_dir(sdkjs_dir)
|
||||
base.copy_dir(sdkjs_dir_mac64, sdkjs_dir)
|
||||
base.copy_dir(sdkjs_dir_host, sdkjs_dir)
|
||||
else:
|
||||
themes_params = []
|
||||
if ("" != config.option("themesparams")):
|
||||
themes_params = ["--params=\"" + config.option("themesparams") + "\""]
|
||||
base.cmd_exe(root_dir + "/converter/allfontsgen", ["--use-system=\"1\"", "--input=\"" + root_dir + "/fonts\"", "--input=\"" + git_dir + "/core-fonts\"", "--allfonts=\"" + root_dir + "/converter/AllFonts.js\"", "--selection=\"" + root_dir + "/converter/font_selection.bin\""])
|
||||
base.cmd_exe(root_dir + "/converter/allthemesgen", ["--converter-dir=\"" + root_dir + "/converter\"", "--src=\"" + root_dir + "/editors/sdkjs/slide/themes\"", "--allfonts=\"AllFonts.js\"", "--output=\"" + root_dir + "/editors/sdkjs/common/Images\""] + themes_params)
|
||||
base.cmd_exe(root_dir + "/converter/allfontsgen", ["--use-system=\"1\"", "--input=\"" + root_dir + "/fonts\"", "--input=\"" + git_dir + "/core-fonts\"", "--allfonts=\"" + root_dir + "/converter/AllFonts.js\"", "--selection=\"" + root_dir + "/converter/font_selection.bin\""], True)
|
||||
base.cmd_exe(root_dir + "/converter/allthemesgen", ["--converter-dir=\"" + root_dir + "/converter\"", "--src=\"" + root_dir + "/editors/sdkjs/slide/themes\"", "--allfonts=\"AllFonts.js\"", "--output=\"" + root_dir + "/editors/sdkjs/common/Images\""] + themes_params, True)
|
||||
base.delete_file(root_dir + "/converter/AllFonts.js")
|
||||
base.delete_file(root_dir + "/converter/font_selection.bin")
|
||||
base.delete_file(root_dir + "/converter/fonts.log")
|
||||
|
||||
base.delete_exe(root_dir + "/converter/allfontsgen")
|
||||
base.delete_exe(root_dir + "/converter/allthemesgen")
|
||||
if not base.is_use_create_artifacts_qemu(platform):
|
||||
base.delete_exe(root_dir + "/converter/allfontsgen")
|
||||
base.delete_exe(root_dir + "/converter/allthemesgen")
|
||||
|
||||
if not isUseJSC:
|
||||
base.delete_file(root_dir + "/editors/sdkjs/slide/sdk-all.cache")
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
@ -18,7 +18,7 @@ def deploy_fonts(git_dir, root_dir, platform=""):
|
||||
if (platform == "android"):
|
||||
base.copy_dir(git_dir + "/core-fonts/dejavu", root_dir + "/fonts/dejavu")
|
||||
base.copy_dir(git_dir + "/core-fonts/liberation", root_dir + "/fonts/liberation")
|
||||
return
|
||||
return
|
||||
|
||||
def make():
|
||||
base_dir = base.get_script_dir() + "/../out"
|
||||
@ -35,7 +35,7 @@ def make():
|
||||
|
||||
if base.get_env("DESTDIR_BUILD_OVERRIDE") != "":
|
||||
return
|
||||
|
||||
|
||||
if (base.is_dir(root_dir)):
|
||||
base.delete_dir(root_dir)
|
||||
base.create_dir(root_dir)
|
||||
@ -57,11 +57,13 @@ def make():
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "PdfFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "DjVuFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "XpsFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "OFDFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HtmlFile2")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HtmlRenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "doctrenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "Fb2File")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "EpubFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "IWorkFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "HWPFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "DocxRenderer")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", root_dir + "/cmap.bin")
|
||||
|
||||
@ -71,29 +73,14 @@ def make():
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "x2t")
|
||||
|
||||
# icu
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icudt58.dll", root_dir + "/icudt58.dll")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icuuc58.dll", root_dir + "/icuuc58.dll")
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.so.58", root_dir + "/libicudata.so.58")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.so.58", root_dir + "/libicuuc.so.58")
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.58.dylib", root_dir + "/libicudata.58.dylib")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.58.dylib", root_dir + "/libicuuc.58.dylib")
|
||||
|
||||
if (0 == platform.find("android")):
|
||||
#base.copy_file(core_dir + "/Common/3dParty/icu/android/build/" + platform[8:] + "/libicudata.so", root_dir + "/libicudata.so")
|
||||
#base.copy_file(core_dir + "/Common/3dParty/icu/android/build/" + platform[8:] + "/libicuuc.so", root_dir + "/libicuuc.so")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/android/build/" + platform[8:] + "/icudt58l.dat", root_dir + "/icudt58l.dat")
|
||||
base.deploy_icu(core_dir, root_dir, platform)
|
||||
|
||||
# js
|
||||
base.copy_dir(base_dir + "/js/" + branding + "/mobile/sdkjs", root_dir + "/sdkjs")
|
||||
|
||||
# correct ios frameworks
|
||||
if ("ios" == platform):
|
||||
base.generate_plist(root_dir)
|
||||
base.for_each_framework(root_dir, "ios", callbacks=[base.generate_plist, base.generate_xcprivacy])
|
||||
deploy_fonts(git_dir, root_dir)
|
||||
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries", True, False)
|
||||
|
||||
@ -113,7 +100,7 @@ def make():
|
||||
deploy_fonts(git_dir, root_dir, "android")
|
||||
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries", True, False)
|
||||
# app
|
||||
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder", "", "./dictionaries")
|
||||
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder", "", "./dictionaries")
|
||||
libs_dir = root_dir + "/lib"
|
||||
base.create_dir(libs_dir + "/arm64-v8a")
|
||||
base.copy_files(base_dir + "/android_arm64_v8a/" + branding + "/mobile/*.so", libs_dir + "/arm64-v8a")
|
||||
|
||||
@ -18,7 +18,7 @@ def make():
|
||||
|
||||
if base.get_env("DESTDIR_BUILD_OVERRIDE") != "":
|
||||
return
|
||||
|
||||
|
||||
if (base.is_dir(root_dir)):
|
||||
base.delete_dir(root_dir)
|
||||
base.create_dir(root_dir)
|
||||
@ -37,7 +37,7 @@ def make():
|
||||
|
||||
# correct ios frameworks
|
||||
if ("ios" == platform):
|
||||
base.generate_plist(root_dir)
|
||||
base.for_each_framework(root_dir, "ios", callbacks=[base.generate_plist, base.generate_xcprivacy])
|
||||
|
||||
for native_platform in platforms:
|
||||
if native_platform == "android":
|
||||
|
||||
@ -58,6 +58,14 @@ def make():
|
||||
base.create_dir(build_server_dir + '/Metrics/node_modules/modern-syslog/build/Release')
|
||||
base.copy_file(server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node", build_server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node")
|
||||
|
||||
# AdminPanel server part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/server')
|
||||
base.copy_exe(server_dir + "/AdminPanel/server", build_server_dir + '/AdminPanel/server', "adminpanel")
|
||||
|
||||
# AdminPanel client part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/client/build')
|
||||
base.copy_dir(server_dir + '/AdminPanel/client/build', build_server_dir + '/AdminPanel/client/build')
|
||||
|
||||
qt_dir = base.qt_setup(native_platform)
|
||||
platform = native_platform
|
||||
|
||||
@ -77,11 +85,13 @@ def make():
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "PdfFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "DjVuFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "XpsFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "OFDFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "HtmlFile2")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "HtmlRenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "doctrenderer")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "Fb2File")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "EpubFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "IWorkFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "HWPFile")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "DocxRenderer")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", converter_dir + "/cmap.bin")
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, converter_dir, "x2t")
|
||||
@ -92,24 +102,18 @@ def make():
|
||||
base.generate_doctrenderer_config(converter_dir + "/DoctRenderer.config", "../../../", "server", "", "../../../dictionaries")
|
||||
|
||||
# icu
|
||||
if (0 == platform.find("win")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icudt58.dll", converter_dir + "/icudt58.dll")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/icuuc58.dll", converter_dir + "/icuuc58.dll")
|
||||
base.deploy_icu(core_dir, converter_dir, platform)
|
||||
|
||||
if (0 == platform.find("linux")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.so.58", converter_dir + "/libicudata.so.58")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.so.58", converter_dir + "/libicuuc.so.58")
|
||||
|
||||
if (0 == platform.find("mac")):
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicudata.58.dylib", converter_dir + "/libicudata.58.dylib")
|
||||
base.copy_file(core_dir + "/Common/3dParty/icu/" + platform + "/build/libicuuc.58.dylib", converter_dir + "/libicuuc.58.dylib")
|
||||
|
||||
base.copy_v8_files(core_dir, converter_dir, platform)
|
||||
|
||||
# builder
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, converter_dir, "docbuilder")
|
||||
base.copy_dir(git_dir + "/document-templates/new/en-US", converter_dir + "/empty")
|
||||
|
||||
# correct mac frameworks
|
||||
if (0 == platform.find("mac")):
|
||||
base.for_each_framework(converter_dir, "mac", callbacks=[base.generate_plist], max_depth=1)
|
||||
|
||||
# js
|
||||
js_dir = root_dir
|
||||
base.copy_dir(base_dir + "/js/" + branding + "/builder/sdkjs", js_dir + "/sdkjs")
|
||||
@ -118,9 +122,11 @@ def make():
|
||||
+ glob.glob(js_dir + "/web-apps/apps/*/mobile/dist/js/*.js.map"):
|
||||
base.delete_file(file)
|
||||
|
||||
base.create_x2t_js_cache(converter_dir, "server", platform)
|
||||
|
||||
# add embed worker code
|
||||
base.cmd_in_dir(git_dir + "/sdkjs/common/embed", "python", ["make.py", js_dir + "/web-apps/apps/api/documents/api.js"])
|
||||
|
||||
|
||||
# plugins
|
||||
base.create_dir(js_dir + "/sdkjs-plugins")
|
||||
base.copy_marketplace_plugin(js_dir + "/sdkjs-plugins", False, True)
|
||||
@ -142,7 +148,7 @@ def make():
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, tools_dir, "allthemesgen")
|
||||
if ("1" != config.option("preinstalled-plugins")):
|
||||
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, tools_dir, "pluginsmanager")
|
||||
|
||||
|
||||
branding_dir = server_dir + "/branding"
|
||||
if("" != config.option("branding") and "onlyoffice" != config.option("branding")):
|
||||
branding_dir = git_dir + '/' + config.option("branding") + '/server'
|
||||
@ -181,6 +187,7 @@ def make():
|
||||
base.copy_file(license_file1, build_server_dir)
|
||||
base.copy_file(license_file2, build_server_dir)
|
||||
base.copy_dir(license_dir, license)
|
||||
base.copy_dir(server_dir + '/dictionaries', build_server_dir + '/dictionaries')
|
||||
|
||||
#branding
|
||||
welcome_files = branding_dir + '/welcome'
|
||||
@ -223,4 +230,3 @@ def make():
|
||||
base.delete_file(root_dir_snap + '/example/nodejs/example')
|
||||
|
||||
return
|
||||
|
||||
|
||||
104
scripts/develop/build_lo_linux.py
Normal file
104
scripts/develop/build_lo_linux.py
Normal file
@ -0,0 +1,104 @@
|
||||
# This script was successfully executed on Ubuntu 22.04.5 LTS
|
||||
|
||||
# Before starting, make sure that:
|
||||
# 1. Python >= 3.9
|
||||
# 2. The current working folder with the script and its path do not contain spaces and use Latin characters.
|
||||
# 3. Antivirus is turned off
|
||||
# 4. There is enough free space on the disk (50GB Libre Office and during the unpacking of packages, it's recommended that you allocate at least 80 gigabytes of free space)
|
||||
# 5. The current working folder with the script and its path do not contain spaces and use Latin characters.
|
||||
|
||||
# If the error "You must put some 'source' URIs in your sources.list" occurs, you need to run the command:
|
||||
# software-properties-gtk
|
||||
# in the terminal, and then under the "Ubuntu Software" tab, click "Source code" if it's not turned on and submit
|
||||
|
||||
# after completion, the file will appear:
|
||||
# current_folder_with_script/libreoffice_build/instdir/soffice
|
||||
# debugging can be done via MVS 2022
|
||||
# https://wiki.documentfoundation.org/Development/IDE#Microsoft_Visual_Studio
|
||||
# or via VS Code with c/c++ tools
|
||||
# https://wiki.documentfoundation.org/Development/IDE#Visual_Studio_Code_(VSCode)
|
||||
# or via Qt Creator
|
||||
# https://wiki.documentfoundation.org/Development/IDE#Qt_Creator
|
||||
# or via attatch to the soffice.bin process
|
||||
# https://wiki.documentfoundation.org/Development/How_to_debug#Debugging_with_gdb
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
CONFIGURE_PARAMS = [
|
||||
"--enable-dbgutil",
|
||||
"--without-doxygen",
|
||||
"--enable-pch",
|
||||
"--disable-ccache",
|
||||
# "--with-visual-studio=2022",
|
||||
'--enable-symbols="all"'
|
||||
]
|
||||
|
||||
SUDO_DEPENDENCIES = [
|
||||
"git", "build-essential", "zip", "ccache", "junit4", "libkrb5-dev", "nasm", "graphviz", "python3",
|
||||
"python3-dev", "python3-setuptools", "qtbase5-dev", "libkf5coreaddons-dev", "libkf5i18n-dev",
|
||||
"libkf5config-dev", "libkf5windowsystem-dev", "libkf5kio-dev", "libqt5x11extras5-dev", "autoconf",
|
||||
"libcups2-dev", "libfontconfig1-dev", "gperf", "openjdk-17-jdk", "doxygen", "libxslt1-dev",
|
||||
"xsltproc", "libxml2-utils", "libxrandr-dev", "libx11-dev", "bison", "flex", "libgtk-3-dev",
|
||||
"libgstreamer-plugins-base1.0-dev", "libgstreamer1.0-dev", "ant", "ant-optional", "libnss3-dev",
|
||||
"libavahi-client-dev", "libxt-dev"
|
||||
]
|
||||
|
||||
DIR_NAME = "libreoffice"
|
||||
OFFICE_PATH = "instdir/program/soffice"
|
||||
|
||||
class bcolors:
|
||||
OKBLUE = '\033[94m'
|
||||
OKCYAN = '\033[96m'
|
||||
OKGREEN = '\033[92m'
|
||||
FAIL = '\033[91m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
def run_command(command, exit_on_error=True):
|
||||
try:
|
||||
subprocess.run(command, shell=True, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"{bcolors.FAIL}Error executing command: {command}{bcolors.RESET}")
|
||||
if exit_on_error:
|
||||
sys.exit(1)
|
||||
|
||||
def install_dependencies():
|
||||
print("Updating package list...")
|
||||
run_command("sudo apt update")
|
||||
|
||||
print("Adding PPA for GCC/G++ update...")
|
||||
run_command("sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test")
|
||||
run_command("sudo apt update")
|
||||
|
||||
print("Installing dependencies for LibreOffice...")
|
||||
run_command("sudo apt-get build-dep -y libreoffice")
|
||||
run_command(f"sudo apt-get install {' '.join(map(str, SUDO_DEPENDENCIES))}")
|
||||
|
||||
print("Updating GCC/G++ to v12...")
|
||||
run_command("sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 60 --slave /usr/bin/g++ g++ /usr/bin/g++-12", exit_on_error=False)
|
||||
|
||||
print(bcolors.OKGREEN + "All dependencies successfully installed!" + bcolors.RESET)
|
||||
|
||||
def build_libreoffice():
|
||||
print("Cloning LibreOffice repository...")
|
||||
run_command(f"git clone https://git.libreoffice.org/core {DIR_NAME}", exit_on_error=False)
|
||||
|
||||
print("Changing to build directory...")
|
||||
os.chdir(f"./{DIR_NAME}")
|
||||
|
||||
print("Start configurator autogen.sh...")
|
||||
run_command(f"./autogen.sh {' '.join(map(str, CONFIGURE_PARAMS))}")
|
||||
|
||||
print(bcolors.OKCYAN + "Starting libreoffice build, this may take up to 24 hours and takes up about 20 GB of drive space. You will also most likely need at least 8 GBs of RAM, otherwise the machine might fall into swap and appear to freeze up..." + bcolors.RESET)
|
||||
run_command("make")
|
||||
|
||||
print(bcolors.OKGREEN + "LibreOffice build completed!" + bcolors.RESET)
|
||||
|
||||
# print(bcolors.OKCYAN + "Running LibreOffice..." + bcolors.RESET)
|
||||
# run_command(OFFICE_PATH, exit_on_error=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
install_dependencies()
|
||||
build_libreoffice()
|
||||
202
scripts/develop/build_lo_windows.py
Normal file
202
scripts/develop/build_lo_windows.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Before starting, make sure that:
|
||||
# 1. MVS 2022 is installed and the necessary individual components are in its installer
|
||||
# <20> Windows Universal C Runtime
|
||||
# <20> .NET Framework 4.x SDK (.NET Framework 5.x SDK and later are currently not supported. These don't register their information to registry, don't have csc.exe and they use dotnet command with csc.dll instead for compiling.)
|
||||
# <20> C++ 20xx Redistributable MSMs (only required to build MSI installer)
|
||||
# <20> C++ Clang Compiler for Windows (x.x.x)
|
||||
# 2. Java JDK >= 17
|
||||
# 3. Antivirus is turned off
|
||||
# 4. There is enough free space on the disk (50GB Libre Office, 50Gb cygwin64)
|
||||
|
||||
# after completion, the files will appear:
|
||||
# {LO_BUILD_PATH}/sources/libo-core/instdir/program/soffice.exe
|
||||
# {LO_BUILD_PATH}/sources/libo-core/LibreOffice.sln
|
||||
# debugging can be done via MVS 2022
|
||||
# https://wiki.documentfoundation.org/Development/IDE#Microsoft_Visual_Studio
|
||||
# or via attatch to the soffice.bin process
|
||||
# https://wiki.documentfoundation.org/Development/How_to_debug#Debugging_with_gdb
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append('../../scripts')
|
||||
import threading
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import argparse
|
||||
import base
|
||||
|
||||
CYGWIN_DOWNLOAD_URL = 'https://cygwin.com/setup-x86_64.exe'
|
||||
CYGWIN_TEMP_PATH = './tmp'
|
||||
CYGWIN_SETUP_FILENAME = 'setup-x86_64.exe'
|
||||
CYGWIN_SETUP_PARAMS = [
|
||||
"-P", "autoconf",
|
||||
"-P", "automake",
|
||||
"-P", "bison",
|
||||
"-P", "cabextract",
|
||||
"-P", "doxygen",
|
||||
"-P", "flex",
|
||||
"-P", "gawk=5.2.2-1",
|
||||
"-P", "gcc-g++",
|
||||
"-P", "gettext-devel",
|
||||
"-P", "git",
|
||||
"-P", "gnupg",
|
||||
"-P", "gperf",
|
||||
"-P", "make",
|
||||
"-P", "mintty",
|
||||
"-P", "nasm",
|
||||
"-P", "openssh",
|
||||
"-P", "openssl",
|
||||
"-P", "patch",
|
||||
"-P", "perl",
|
||||
"-P", "python",
|
||||
"-P", "python3",
|
||||
"-P", "pkg-config",
|
||||
"-P", "rsync",
|
||||
"-P", "unzip",
|
||||
"-P", "vim",
|
||||
"-P", "wget",
|
||||
"-P", "zip",
|
||||
"-P", "perl-Archive-Zip",
|
||||
"-P", "perl-Font-TTF",
|
||||
"-P", "perl-IO-String",
|
||||
"--no-admin",
|
||||
"--quiet-mode"
|
||||
]
|
||||
CYGWIN_BAT_PATH = 'C:/cygwin64/Cygwin.bat'
|
||||
LO_BUILD_PATH = os.path.normpath(os.path.join(os.getcwd(), '../../../LO'))
|
||||
|
||||
CONFIGURE_PARAMS = [f'--with-external-tar="{LO_BUILD_PATH}/sources/lo-externalsrc"',
|
||||
f'--with-junit="{LO_BUILD_PATH}/sources/junit-4.10.jar"',
|
||||
f'--with-ant-home="{LO_BUILD_PATH}/sources/apache-ant-1.9.5"',
|
||||
"--enable-pch",
|
||||
"--disable-ccache",
|
||||
"--with-visual-studio=2022",
|
||||
"--enable-dbgutil",
|
||||
'--enable-symbols="all"']
|
||||
|
||||
|
||||
def create_folder_safe(folder_path):
|
||||
if not os.path.exists(folder_path):
|
||||
try:
|
||||
os.mkdir(folder_path)
|
||||
print(f"Folder '{folder_path}' created successfully.")
|
||||
except Exception as e:
|
||||
print(f"Error creating folder: {e}")
|
||||
else:
|
||||
print(f"Folder '{folder_path}' already exists.")
|
||||
|
||||
|
||||
class CygwinRunner:
|
||||
@staticmethod
|
||||
def process_commands(commands: list[str]):
|
||||
proc = subprocess.Popen(
|
||||
[CYGWIN_BAT_PATH], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
|
||||
shell=True, creationflags=subprocess.CREATE_NEW_CONSOLE
|
||||
)
|
||||
|
||||
def read_stdout():
|
||||
for line in iter(proc.stdout.readline, ''):
|
||||
sys.stdout.write(line)
|
||||
proc.stdout.close()
|
||||
|
||||
def read_stderr():
|
||||
for line in iter(proc.stderr.readline, ''):
|
||||
sys.stderr.write(line)
|
||||
proc.stderr.close()
|
||||
|
||||
stdout_thread = threading.Thread(target=read_stdout)
|
||||
stderr_thread = threading.Thread(target=read_stderr)
|
||||
|
||||
stdout_thread.start()
|
||||
stderr_thread.start()
|
||||
|
||||
for command in commands:
|
||||
proc.stdin.write(command + '\n')
|
||||
proc.stdin.flush()
|
||||
|
||||
stdout_thread.join()
|
||||
stderr_thread.join()
|
||||
|
||||
proc.stdin.close()
|
||||
|
||||
proc.wait()
|
||||
|
||||
@staticmethod
|
||||
def install_gnu_make():
|
||||
base.print_info("install_gnu_make")
|
||||
commands = ['mkdir -p /opt/lo/bin',
|
||||
'cd /opt/lo/bin',
|
||||
'wget https://dev-www.libreoffice.org/bin/cygwin/make-4.2.1-msvc.exe',
|
||||
'cp make-4.2.1-msvc.exe make',
|
||||
'chmod +x make',
|
||||
'exit']
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
@staticmethod
|
||||
def install_ant_and_junit():
|
||||
base.print_info("install_ant_and_junit")
|
||||
commands = [f'mkdir -p {LO_BUILD_PATH}/sources',
|
||||
f'cd {LO_BUILD_PATH}/sources',
|
||||
'wget https://archive.apache.org/dist/ant/binaries/apache-ant-1.9.5-bin.tar.bz2',
|
||||
'tar -xjvf apache-ant-1.9.5-bin.tar.bz2',
|
||||
'wget http://downloads.sourceforge.net/project/junit/junit/4.10/junit-4.10.jar',
|
||||
'exit']
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
@staticmethod
|
||||
def clone_lo():
|
||||
base.print_info("clone_lo")
|
||||
commands = [f'cd {LO_BUILD_PATH}/sources',
|
||||
'git clone https://gerrit.libreoffice.org/core libo-core',
|
||||
'exit']
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
@staticmethod
|
||||
def build_autogen():
|
||||
base.print_info("build_autogen")
|
||||
commands = [f'cd {LO_BUILD_PATH}/sources/libo-core',
|
||||
f"./autogen.sh {' '.join(map(str, CONFIGURE_PARAMS))}",
|
||||
'exit']
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
@staticmethod
|
||||
def run_make_build():
|
||||
base.print_info("run_make")
|
||||
commands = [f'cd {LO_BUILD_PATH}/sources/libo-core',
|
||||
f'/opt/lo/bin/make gb_COLOR=1',
|
||||
"exit"]
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
@staticmethod
|
||||
def build_vs_integration():
|
||||
base.print_info("run_make")
|
||||
commands = [f'cd {LO_BUILD_PATH}/sources/libo-core',
|
||||
f'/opt/lo/bin/make gb_COLOR=1 vs-ide-integration',
|
||||
"exit"]
|
||||
CygwinRunner.process_commands(commands)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="options")
|
||||
parser.add_argument("--lo_build_path", dest="build_path", default=f'../../../LO')
|
||||
parser.add_argument("--disable_sln", dest="disable_sln", action=argparse.BooleanOptionalAction)
|
||||
args = parser.parse_args()
|
||||
|
||||
LO_BUILD_PATH = args.build_path
|
||||
DISABLE_SLN = args.disable_sln
|
||||
create_folder_safe(f'{LO_BUILD_PATH}/sources/lo-externalsrc')
|
||||
create_folder_safe(CYGWIN_TEMP_PATH)
|
||||
os.chdir(CYGWIN_TEMP_PATH)
|
||||
base.download(CYGWIN_DOWNLOAD_URL, CYGWIN_SETUP_FILENAME)
|
||||
subprocess.run([CYGWIN_SETUP_FILENAME] + CYGWIN_SETUP_PARAMS)
|
||||
os.chdir('..')
|
||||
shutil.rmtree(CYGWIN_TEMP_PATH)
|
||||
CygwinRunner.install_gnu_make()
|
||||
CygwinRunner.install_ant_and_junit()
|
||||
CygwinRunner.clone_lo()
|
||||
CygwinRunner.build_autogen()
|
||||
CygwinRunner.run_make_build()
|
||||
if not DISABLE_SLN:
|
||||
CygwinRunner.build_vs_integration()
|
||||
@ -5,9 +5,6 @@ import base
|
||||
import os
|
||||
import json
|
||||
|
||||
def get_core_url(arch, branch):
|
||||
return "http://repo-doc-onlyoffice-com.s3.amazonaws.com/" + base.host_platform() + "/core/" + branch + "/latest/" + arch + "/core.7z"
|
||||
|
||||
def make():
|
||||
git_dir = base.get_script_dir() + "/../.."
|
||||
old_cur = os.getcwd()
|
||||
@ -18,16 +15,10 @@ def make():
|
||||
|
||||
os.chdir(work_dir)
|
||||
|
||||
arch = "x64"
|
||||
arch2 = "_64"
|
||||
if ("windows" == base.host_platform()) and not base.host_platform_is64():
|
||||
arch = "x86"
|
||||
arch2 = "_32"
|
||||
|
||||
url = get_core_url(arch, config.option("branch"))
|
||||
url = base.get_autobuild_version("core", "", config.option("branch"))
|
||||
data_url = base.get_file_last_modified_url(url)
|
||||
if (data_url == "" and config.option("branch") != "develop"):
|
||||
url = get_core_url(arch, "develop")
|
||||
url = base.get_autobuild_version("core", "", "develop")
|
||||
data_url = base.get_file_last_modified_url(url)
|
||||
|
||||
old_data_url = base.readFile("./core.7z.data")
|
||||
@ -49,12 +40,6 @@ def make():
|
||||
base.extract("./core.7z", "./")
|
||||
base.writeFile("./core.7z.data", data_url)
|
||||
|
||||
platform = ""
|
||||
if ("windows" == base.host_platform()):
|
||||
platform = "win" + arch2
|
||||
else:
|
||||
platform = base.host_platform() + arch2
|
||||
|
||||
base.copy_files("./core/*", "./")
|
||||
else:
|
||||
print("-----------------------------------------------------------")
|
||||
|
||||
@ -539,7 +539,9 @@ def check_mysqlServer():
|
||||
print(mysql_full_name + 'configuration is valid')
|
||||
dependence.sqlPath = info['Location']
|
||||
return dependence
|
||||
print(mysql_full_name + 'configuration is not valid')
|
||||
print(mysql_full_name + 'configuration is not valid:' + connectionResult)
|
||||
# if path exists, then further removal and installation fails(according to startup statistics). it is better to fix issue manually.
|
||||
return dependence
|
||||
|
||||
print('Valid MySQL Server not found')
|
||||
dependence.append_uninstall('MySQL Server')
|
||||
|
||||
342
scripts/develop/git_operations.py
Normal file
342
scripts/develop/git_operations.py
Normal file
@ -0,0 +1,342 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Git Operations Script
|
||||
Provides functionality to clone repositories and create branches.
|
||||
Uses existing methods from base module and integrates with release.py patterns.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
# Add parent directory to path to import modules
|
||||
sys.path.append('../')
|
||||
import base
|
||||
import config
|
||||
import dependence
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GitOperations:
|
||||
"""Class to handle git clone and branch creation using existing base module methods."""
|
||||
|
||||
def __init__(self, branding: str = "onlyoffice", base_branch: str = "develop",
|
||||
branding_url: str = "ONLYOFFICE/onlyoffice.git", branch_name: str = None,
|
||||
modules: str = "core desktop builder server mobile"):
|
||||
"""
|
||||
Initialize GitOperations with branding configuration and configure repositories.
|
||||
|
||||
Args:
|
||||
branding: Branding name (default: onlyoffice)
|
||||
base_branch: Base branch to work from (default: develop)
|
||||
branding_url: Relative path from git host base (default: ONLYOFFICE/onlyoffice.git)
|
||||
branch_name: Name of the branch to create (required for branch operations)
|
||||
modules: Modules to include (default: core desktop builder server mobile)
|
||||
"""
|
||||
self.branding = branding
|
||||
self.base_branch = base_branch
|
||||
self.branding_url = branding_url
|
||||
self.branch_name = branch_name
|
||||
self.modules = modules
|
||||
self.work_dir = None
|
||||
|
||||
# Configure repositories immediately
|
||||
self._configure()
|
||||
|
||||
# Update repositories after configuration
|
||||
repositories = self.get_configured_repositories()
|
||||
#base.update_repositories(repositories)
|
||||
|
||||
def create_branch(self, branch_name: str, repo_dir: str = None) -> bool:
|
||||
"""
|
||||
Create a new branch using base.cmd_in_dir.
|
||||
|
||||
Args:
|
||||
branch_name: Name of the new branch
|
||||
repo_dir: Repository directory (optional, uses current if not specified)
|
||||
from_branch: Branch to create from (optional, uses current if not specified)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
work_dir = repo_dir or self.work_dir
|
||||
logger.info(f"Creating branch '{branch_name}' in {work_dir}")
|
||||
|
||||
try:
|
||||
# Create and checkout new branch
|
||||
base.cmd_in_dir(work_dir, "git", ["checkout", "-b", branch_name], True)
|
||||
logger.info(f"Successfully created branch: {branch_name}")
|
||||
return True
|
||||
except SystemExit:
|
||||
logger.error(f"Failed to create branch: {branch_name}")
|
||||
return False
|
||||
|
||||
def push_branch(self, branch_name: str, repo_dir: str = None, set_upstream: bool = True) -> bool:
|
||||
"""
|
||||
Push a branch to remote repository using base.cmd_in_dir.
|
||||
|
||||
Args:
|
||||
branch_name: Name of the branch to push
|
||||
repo_dir: Repository directory (optional, uses current if not specified)
|
||||
set_upstream: Whether to set upstream tracking (default: True)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
work_dir = repo_dir or self.work_dir
|
||||
logger.info(f"Pushing branch '{branch_name}' in {work_dir}")
|
||||
|
||||
try:
|
||||
if set_upstream:
|
||||
# Push branch and set upstream tracking
|
||||
base.cmd_in_dir(work_dir, "git", ["push", "-u", "origin", branch_name], True)
|
||||
else:
|
||||
# Just push the branch
|
||||
base.cmd_in_dir(work_dir, "git", ["push", "origin", branch_name], True)
|
||||
|
||||
logger.info(f"Successfully pushed branch: {branch_name}")
|
||||
return True
|
||||
except SystemExit:
|
||||
logger.error(f"Failed to push branch: {branch_name}")
|
||||
return False
|
||||
|
||||
def _configure(self) -> bool:
|
||||
"""
|
||||
Configure repositories using existing configure.py pattern from release.py.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
logger.info(f"Configuring and cloning repositories for branch: {self.base_branch}")
|
||||
|
||||
try:
|
||||
# Get build_tools origin and construct branding URL from git host base
|
||||
build_tools_origin = base.git_get_origin()
|
||||
# Extract git host base (everything up to the host)
|
||||
# For https://github.com/ORG/build_tools.git -> https://github.com/
|
||||
# For git@github.com:ORG/build_tools.git -> git@github.com:
|
||||
if '://' in build_tools_origin: # HTTPS
|
||||
host_base = build_tools_origin.split('/', 3)[0] + '//' + build_tools_origin.split('/', 3)[2] + '/'
|
||||
else: # SSH
|
||||
host_base = build_tools_origin.split(':', 1)[0] + ':'
|
||||
|
||||
branding_url = host_base + self.branding_url
|
||||
|
||||
logger.info(f"Build tools origin: {build_tools_origin}")
|
||||
logger.info(f"Git host base: {host_base}")
|
||||
logger.info(f"Using branding URL: {branding_url}")
|
||||
|
||||
# Check platform and dependencies like in release.py
|
||||
platform = base.host_platform()
|
||||
if platform == "windows":
|
||||
dependence.check_pythonPath()
|
||||
dependence.check_gitPath()
|
||||
|
||||
# Run configure.py like in release.py
|
||||
configure_args = [
|
||||
'configure.py',
|
||||
'--branding', self.branding,
|
||||
'--branding-url', branding_url,
|
||||
'--branch', self.base_branch,
|
||||
'--module', self.modules,
|
||||
'--update', '1',
|
||||
'--clean', '0'
|
||||
]
|
||||
|
||||
base.cmd_in_dir('../../', 'python', configure_args)
|
||||
|
||||
# Parse configuration like in release.py
|
||||
config.parse()
|
||||
|
||||
# Update build_tools repository
|
||||
base.git_update('build_tools')
|
||||
|
||||
# Update branding repository
|
||||
base.git_update(self.branding)
|
||||
|
||||
# Correct defaults (the branding repo is already updated)
|
||||
config.parse_defaults()
|
||||
|
||||
logger.info("Successfully configured")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to configure and clone: {e}")
|
||||
return False
|
||||
|
||||
def get_configured_repositories(self) -> Dict:
|
||||
"""Get repositories using existing base.get_repositories() pattern from release.py."""
|
||||
repositories = base.get_repositories()
|
||||
repositories['core-ext'] = [True, False]
|
||||
repositories['build_tools'] = [True, False]
|
||||
repositories[self.branding] = [True, False]
|
||||
return repositories
|
||||
|
||||
def _iterate_repositories(self, operation_func, operation_name: str) -> bool:
|
||||
"""
|
||||
Iterate over all repositories and apply the given operation function.
|
||||
|
||||
Args:
|
||||
operation_func: Function to apply to each repository (takes repo_name and repo_path)
|
||||
operation_name: Name of the operation for logging
|
||||
|
||||
Returns:
|
||||
bool: True if at least one operation succeeded, False otherwise
|
||||
"""
|
||||
repositories = self.get_configured_repositories()
|
||||
success_count = 0
|
||||
total_count = len(repositories)
|
||||
|
||||
for repo_name in repositories:
|
||||
current_dir = repositories[repo_name][1]
|
||||
repo_path = f"../../../{repo_name}" if current_dir == False else current_dir
|
||||
|
||||
if base.is_dir(repo_path):
|
||||
if operation_func(repo_name, repo_path):
|
||||
success_count += 1
|
||||
else:
|
||||
logger.warning(f"✗ Failed to {operation_name} in {repo_name}")
|
||||
else:
|
||||
logger.warning(f"Repository {repo_name} not found at {repo_path}")
|
||||
|
||||
logger.info(f"{operation_name.capitalize()} completed in {success_count}/{total_count} repositories")
|
||||
return success_count > 0
|
||||
|
||||
def delete_branch(self, branch_name: str, repo_dir: str = None, force: bool = False) -> bool:
|
||||
"""
|
||||
Delete a branch using base.cmd_in_dir.
|
||||
|
||||
Args:
|
||||
branch_name: Name of the branch to delete
|
||||
repo_dir: Repository directory (optional, uses current if not specified)
|
||||
force: Whether to force delete the branch (default: False)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
work_dir = repo_dir or self.work_dir
|
||||
logger.info(f"Deleting branch '{branch_name}' in {work_dir}")
|
||||
|
||||
try:
|
||||
# Switch to base branch first to avoid deleting current branch
|
||||
base.cmd_in_dir(work_dir, "git", ["checkout", self.base_branch], True)
|
||||
|
||||
# Delete local branch
|
||||
delete_flag = "-D" if force else "-d"
|
||||
base.cmd_in_dir(work_dir, "git", ["branch", delete_flag, branch_name], True)
|
||||
logger.info(f"Successfully deleted local branch: {branch_name}")
|
||||
|
||||
# Delete remote branch
|
||||
try:
|
||||
base.cmd_in_dir(work_dir, "git", ["push", "origin", "--delete", branch_name], True)
|
||||
logger.info(f"Successfully deleted remote branch: {branch_name}")
|
||||
except SystemExit:
|
||||
logger.warning(f"Failed to delete remote branch: {branch_name} (may not exist)")
|
||||
|
||||
return True
|
||||
except SystemExit:
|
||||
logger.error(f"Failed to delete branch: {branch_name}")
|
||||
return False
|
||||
|
||||
def create_branches(self) -> bool:
|
||||
"""
|
||||
Create a branch with the given name in all repositories.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
logger.info(f"Creating branch '{self.branch_name}' in all repositories")
|
||||
|
||||
def create_and_push_branch(repo_name: str, repo_path: str) -> bool:
|
||||
"""Create and push branch for a single repository."""
|
||||
if self.create_branch(self.branch_name, repo_path):
|
||||
logger.info(f"✓ Created branch '{self.branch_name}' in {repo_name}")
|
||||
# Push the created branch
|
||||
if self.push_branch(self.branch_name, repo_path):
|
||||
logger.info(f"✓ Pushed branch '{self.branch_name}' in {repo_name}")
|
||||
return True
|
||||
else:
|
||||
logger.warning(f"✗ Failed to push branch '{self.branch_name}' in {repo_name}")
|
||||
return False
|
||||
else:
|
||||
logger.warning(f"✗ Failed to create branch '{self.branch_name}' in {repo_name}")
|
||||
return False
|
||||
|
||||
try:
|
||||
return self._iterate_repositories(create_and_push_branch, f"create and push branch '{self.branch_name}'")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create branch in all repositories: {e}")
|
||||
return False
|
||||
|
||||
def remove_branches(self, force: bool = False) -> bool:
|
||||
"""
|
||||
Remove a branch with the given name from all repositories.
|
||||
|
||||
Args:
|
||||
force: Whether to force delete the branch (default: False)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
logger.info(f"Removing branch '{self.branch_name}' from all repositories")
|
||||
|
||||
def delete_branch_operation(repo_name: str, repo_path: str) -> bool:
|
||||
"""Delete branch for a single repository."""
|
||||
if self.delete_branch(self.branch_name, repo_path, force):
|
||||
logger.info(f"✓ Removed branch '{self.branch_name}' from {repo_name}")
|
||||
return True
|
||||
else:
|
||||
logger.warning(f"✗ Failed to remove branch '{self.branch_name}' from {repo_name}")
|
||||
return False
|
||||
|
||||
try:
|
||||
return self._iterate_repositories(delete_branch_operation, f"remove branch '{self.branch_name}'")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to remove branch from all repositories: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to handle command line arguments."""
|
||||
parser = argparse.ArgumentParser(description='Git Operations Tool - Create and Remove Branches')
|
||||
subparsers = parser.add_subparsers(dest='command', help='Available commands')
|
||||
|
||||
# Create branch command (configure, clone and create branch in all repositories)
|
||||
branch_parser = subparsers.add_parser('create', help='Configure, clone and create branch in all repositories')
|
||||
branch_parser.add_argument('branch_name', help='Name of the branch to create')
|
||||
branch_parser.add_argument('--base-branch', default='develop', help='Base branch to work from (default: develop)')
|
||||
branch_parser.add_argument('--branding', default='onlyoffice', help='Branding name')
|
||||
branch_parser.add_argument('--branding-url', default='ONLYOFFICE/onlyoffice.git', help='Relative path from git host base (default: ONLYOFFICE/onlyoffice.git)')
|
||||
branch_parser.add_argument('--modules', default='core desktop builder server mobile', help='Modules to include')
|
||||
|
||||
# Remove branch command (configure, clone and remove branch from all repositories)
|
||||
remove_parser = subparsers.add_parser('remove', help='Configure, clone and remove branch from all repositories')
|
||||
remove_parser.add_argument('branch_name', help='Name of the branch to remove')
|
||||
remove_parser.add_argument('--base-branch', default='develop', help='Base branch to work from (default: develop)')
|
||||
remove_parser.add_argument('--branding', default='onlyoffice', help='Branding name')
|
||||
remove_parser.add_argument('--branding-url', default='ONLYOFFICE/onlyoffice.git', help='Relative path from git host base (default: ONLYOFFICE/onlyoffice.git)')
|
||||
remove_parser.add_argument('--modules', default='core desktop builder server mobile', help='Modules to include')
|
||||
remove_parser.add_argument('--force', action='store_true', help='Force delete the branch (equivalent to git branch -D)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.command:
|
||||
parser.print_help()
|
||||
return
|
||||
|
||||
git_ops = GitOperations(args.branding, args.base_branch, args.branding_url, args.branch_name, args.modules)
|
||||
|
||||
if args.command == 'create':
|
||||
success = git_ops.create_branches()
|
||||
sys.exit(0 if success else 1)
|
||||
elif args.command == 'remove':
|
||||
success = git_ops.remove_branches(args.force)
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -6,6 +6,7 @@ import base
|
||||
import shutil
|
||||
import optparse
|
||||
import dependence
|
||||
import config
|
||||
|
||||
arguments = sys.argv[1:]
|
||||
|
||||
@ -17,6 +18,10 @@ parser.add_option("--remove-path", action="append", type="string", dest="remove-
|
||||
(options, args) = parser.parse_args(arguments)
|
||||
configOptions = vars(options)
|
||||
|
||||
# parse configuration
|
||||
config.parse()
|
||||
config.parse_defaults()
|
||||
|
||||
for item in configOptions["uninstall"]:
|
||||
dependence.uninstallProgram(item)
|
||||
for item in configOptions["remove-path"]:
|
||||
|
||||
@ -8,6 +8,13 @@ import dependence
|
||||
import traceback
|
||||
import develop
|
||||
|
||||
# if (sys.version_info[0] >= 3):
|
||||
# unicode = str
|
||||
|
||||
# host_platform = base.host_platform()
|
||||
# if (host_platform == 'windows'):
|
||||
# import libwindows
|
||||
|
||||
base_dir = base.get_script_dir(__file__)
|
||||
|
||||
def install_module(path):
|
||||
@ -21,11 +28,18 @@ def find_rabbitmqctl(base_path):
|
||||
return base.find_file(os.path.join(base_path, 'RabbitMQ Server'), 'rabbitmqctl.bat')
|
||||
|
||||
def restart_win_rabbit():
|
||||
# todo maybe restarting is not relevant after many years and versions?
|
||||
base.print_info('restart RabbitMQ node to prevent "Erl.exe high CPU usage every Monday morning on Windows" https://groups.google.com/forum/#!topic/rabbitmq-users/myl74gsYyYg')
|
||||
rabbitmqctl = find_rabbitmqctl(os.environ['PROGRAMW6432']) or find_rabbitmqctl(os.environ['ProgramFiles(x86)'])
|
||||
if rabbitmqctl is not None:
|
||||
base.cmd_in_dir(base.get_script_dir(rabbitmqctl), 'rabbitmqctl.bat', ['stop_app'])
|
||||
base.cmd_in_dir(base.get_script_dir(rabbitmqctl), 'rabbitmqctl.bat', ['start_app'])
|
||||
try:
|
||||
# code = libwindows.sudo(unicode(sys.executable), ['net', 'stop', 'rabbitmq'])
|
||||
# code = libwindows.sudo(unicode(sys.executable), ['net', 'start', 'rabbitmq'])
|
||||
base.cmd_in_dir(base.get_script_dir(rabbitmqctl), 'rabbitmqctl.bat', ['stop_app'])
|
||||
base.cmd_in_dir(base.get_script_dir(rabbitmqctl), 'rabbitmqctl.bat', ['start_app'])
|
||||
except SystemExit:
|
||||
base.print_error('Perhaps Erlang cookies are different: Replace %userprofile%/.erlang.cookie with %WINDIR%/System32/config/systemprofile/.erlang.cookie')
|
||||
raise
|
||||
else:
|
||||
base.print_info('Missing rabbitmqctl.bat')
|
||||
|
||||
|
||||
@ -21,14 +21,15 @@
|
||||
"core/DesktopEditor/raster/JBig2",
|
||||
"core/DesktopEditor/raster/Jp2",
|
||||
"core/DesktopEditor/xml/libxml2",
|
||||
"core/DesktopEditor/xmlsec",
|
||||
"core/DesktopEditor/xmlsec",
|
||||
"core/DjVuFile/libdjvu",
|
||||
"core/DjVuFile/wasm",
|
||||
"core/EpubFile",
|
||||
"core/OOXML/PPTXFormat/Limit/pri",
|
||||
"core/Fb2File",
|
||||
"core/HtmlFile2",
|
||||
"core/HtmlFile2",
|
||||
"core/Apple",
|
||||
"core/HwpFile",
|
||||
"core/OdfFile/Common/utf8cpp",
|
||||
"core/OfficeUtils/js/emsdk",
|
||||
"core/OfficeUtils/src/zlib-1.2.11",
|
||||
@ -197,6 +198,11 @@
|
||||
"editors-ios/Vendor/ThreadSafeMutable/ThreadSafeMutableDictionary.h",
|
||||
"editors-ios/Vendor/ThreadSafeMutable/ThreadSafeMutableDictionary.m"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dir": "editors-webview-ios",
|
||||
"fileExtensions": [".swift", ".xcconfig"],
|
||||
"licensePath": "header.license",
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2024
|
||||
* (c) Copyright Ascensio System SIA 2010-2025
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
|
||||
32
scripts/min.py
Normal file
32
scripts/min.py
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../build_tools/scripts')
|
||||
import base
|
||||
import os
|
||||
|
||||
args = sys.argv[1:]
|
||||
|
||||
if (1 > len(args)):
|
||||
print("Please use min.py PATH_TO_SCRIPT.js")
|
||||
exit(0)
|
||||
|
||||
script_path = args[0]
|
||||
script_path = os.path.abspath(script_path)
|
||||
script_dir = os.path.dirname(script_path)
|
||||
|
||||
script_name = os.path.splitext(os.path.basename(script_path))[0]
|
||||
script_path_min = os.path.join(script_dir, script_name + ".min.js")
|
||||
|
||||
#compilation_level = "WHITESPACE_ONLY"
|
||||
compilation_level = "SIMPLE_OPTIMIZATIONS"
|
||||
base.cmd("java", ["-jar", "../../sdkjs/build/node_modules/google-closure-compiler-java/compiler.jar",
|
||||
"--compilation_level", compilation_level,
|
||||
"--js_output_file", script_path_min,
|
||||
"--js", script_path])
|
||||
|
||||
dev_content = base.readFile(script_path)
|
||||
license = dev_content[0:dev_content.find("*/")+2]
|
||||
min_content = base.readFile(script_path_min)
|
||||
base.delete_file(script_path_min)
|
||||
base.writeFile(script_path_min, license + "\n\n" + min_content)
|
||||
@ -30,23 +30,6 @@ if utils.is_macos():
|
||||
builder_product_name = "Document Builder"
|
||||
|
||||
if utils.is_linux():
|
||||
builder_make_targets = [
|
||||
{
|
||||
"make": "tar",
|
||||
"src": "tar/*.tar*",
|
||||
"dst": "builder/linux/generic/"
|
||||
},
|
||||
{
|
||||
"make": "deb",
|
||||
"src": "deb/*.deb",
|
||||
"dst": "builder/linux/debian/"
|
||||
},
|
||||
{
|
||||
"make": "rpm",
|
||||
"src": "rpm/builddir/RPMS/*/*.rpm",
|
||||
"dst": "builder/linux/rhel/"
|
||||
}
|
||||
]
|
||||
desktop_make_targets = [
|
||||
{
|
||||
"make": "tar",
|
||||
|
||||
@ -7,14 +7,17 @@ import package_branding as branding
|
||||
|
||||
def make():
|
||||
utils.log_h1("BUILDER")
|
||||
if not (utils.is_windows() or utils.is_macos() or utils.is_linux()):
|
||||
utils.log("Unsupported host OS")
|
||||
return
|
||||
if common.deploy:
|
||||
make_archive()
|
||||
if utils.is_windows():
|
||||
make_windows()
|
||||
elif utils.is_macos():
|
||||
make_macos()
|
||||
make_macos_linux()
|
||||
elif utils.is_linux():
|
||||
make_linux()
|
||||
else:
|
||||
utils.log("Unsupported host OS")
|
||||
make_macos_linux()
|
||||
return
|
||||
|
||||
def s3_upload(files, dst):
|
||||
@ -24,132 +27,203 @@ def s3_upload(files, dst):
|
||||
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
|
||||
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
|
||||
if upload:
|
||||
utils.add_deploy_data(key)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
ret &= upload
|
||||
return ret
|
||||
|
||||
def make_archive():
|
||||
utils.set_cwd(utils.get_path(
|
||||
"build_tools/out/" + common.prefix + "/" + branding.company_name.lower()))
|
||||
|
||||
utils.log_h2("builder archive build")
|
||||
utils.delete_file("builder.7z")
|
||||
args = ["7z", "a", "-y", "builder.7z", "./documentbuilder/*"]
|
||||
if utils.is_windows():
|
||||
ret = utils.cmd(*args, verbose=True)
|
||||
else:
|
||||
ret = utils.sh(" ".join(args), verbose=True)
|
||||
utils.set_summary("builder archive build", ret)
|
||||
|
||||
utils.log_h2("builder archive deploy")
|
||||
dest = "builder-" + common.prefix.replace("_","-") + ".7z"
|
||||
dest_latest = "archive/%s/latest/%s" % (common.branch, dest)
|
||||
dest_version = "archive/%s/%s/%s" % (common.branch, common.build, dest)
|
||||
ret = utils.s3_upload(
|
||||
"builder.7z", "s3://" + branding.s3_bucket + "/" + dest_version)
|
||||
utils.set_summary("builder archive deploy", ret)
|
||||
if ret:
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_version)
|
||||
utils.s3_copy(
|
||||
"s3://" + branding.s3_bucket + "/" + dest_version,
|
||||
"s3://" + branding.s3_bucket + "/" + dest_latest)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_latest)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def make_windows():
|
||||
global inno_file, zip_file, suffix, key_prefix
|
||||
global package_version, arch
|
||||
utils.set_cwd("document-builder-package")
|
||||
|
||||
prefix = common.platformPrefixes[common.platform]
|
||||
company = branding.company_name
|
||||
product = branding.builder_product_name.replace(" ","")
|
||||
source_dir = "..\\build_tools\\out\\%s\\%s\\%s" % (prefix, company, product)
|
||||
package_name = company + "-" + product
|
||||
package_version = common.version + "." + common.build
|
||||
suffix = {
|
||||
arch = {
|
||||
"windows_x64": "x64",
|
||||
"windows_x86": "x86"
|
||||
}[common.platform]
|
||||
zip_file = "%s-%s-%s-%s.zip" % (company, product, package_version, suffix)
|
||||
inno_file = "%s-%s-%s-%s.exe" % (company, product, package_version, suffix)
|
||||
|
||||
if common.clean:
|
||||
utils.log_h2("builder clean")
|
||||
utils.delete_dir("build")
|
||||
utils.delete_dir("zip")
|
||||
|
||||
utils.log_h2("copy arifacts")
|
||||
utils.create_dir("build\\app")
|
||||
utils.copy_dir_content(source_dir, "build\\app\\")
|
||||
|
||||
make_zip()
|
||||
make_inno()
|
||||
if make_prepare():
|
||||
make_zip()
|
||||
make_wheel()
|
||||
else:
|
||||
utils.set_summary("builder zip build", False)
|
||||
utils.set_summary("builder python wheel build", False)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def make_zip():
|
||||
utils.log_h2("builder zip build")
|
||||
utils.log_h3(zip_file)
|
||||
def make_prepare():
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
|
||||
ret = utils.cmd("7z", "a", "-y", zip_file, ".\\app\\*",
|
||||
chdir="build", creates="build\\" + zip_file, verbose=True)
|
||||
utils.log_h2("builder prepare")
|
||||
ret = utils.ps1("make.ps1", args, verbose=True)
|
||||
utils.set_summary("builder prepare", ret)
|
||||
return ret
|
||||
|
||||
def make_zip():
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
]
|
||||
# if common.sign:
|
||||
# args += ["-Sign"]
|
||||
|
||||
utils.log_h2("builder zip build")
|
||||
ret = utils.ps1("make_zip.ps1", args, verbose=True)
|
||||
utils.set_summary("builder zip build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("builder zip deploy")
|
||||
ret = s3_upload(["build\\" + zip_file], "builder/win/generic/")
|
||||
ret = s3_upload(utils.glob_path("zip/*.zip"), "builder/win/generic/")
|
||||
utils.set_summary("builder zip deploy", ret)
|
||||
return
|
||||
|
||||
def make_inno():
|
||||
utils.log_h2("builder inno build")
|
||||
utils.log_h3(inno_file)
|
||||
def make_macos_linux():
|
||||
utils.set_cwd("document-builder-package")
|
||||
|
||||
args = [
|
||||
"-Arch", suffix,
|
||||
"-Version", common.version,
|
||||
"-Build", common.build
|
||||
]
|
||||
if not branding.onlyoffice:
|
||||
args += [
|
||||
"-Branding", "%s\\%s\\document-builder-package\\exe" % (common.workspace_dir, common.branding)
|
||||
]
|
||||
if common.sign:
|
||||
args += [
|
||||
"-Sign",
|
||||
"-CertName", branding.cert_name
|
||||
]
|
||||
ret = utils.ps1(
|
||||
"make_inno.ps1", args, creates="build\\" + inno_file, verbose=True
|
||||
)
|
||||
utils.set_summary("builder inno build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("builder inno deploy")
|
||||
ret = s3_upload(["build\\" + inno_file], "builder/win/inno/")
|
||||
utils.set_summary("builder inno deploy", ret)
|
||||
return
|
||||
|
||||
def make_macos():
|
||||
company = branding.company_name.lower()
|
||||
product = branding.builder_product_name.replace(" ","").lower()
|
||||
source_dir = "build_tools/out/%s/%s/%s" % (common.prefix, company, product)
|
||||
arch_list = {
|
||||
"darwin_x86_64": "x86_64",
|
||||
"darwin_arm64": "arm64"
|
||||
}
|
||||
suffix = arch_list[common.platform]
|
||||
builder_tar = "../%s-%s-%s-%s-%s.tar.xz" % \
|
||||
(company, product, common.version, common.build, suffix)
|
||||
|
||||
utils.set_cwd(source_dir)
|
||||
|
||||
if common.clean:
|
||||
utils.log_h2("builder clean")
|
||||
utils.delete_files("../*.tar*")
|
||||
|
||||
utils.log_h2("builder build")
|
||||
ret = utils.sh("tar --xz -cvf %s *" % builder_tar, creates=builder_tar, verbose=True)
|
||||
utils.set_summary("builder build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("builder deploy")
|
||||
ret = s3_upload([builder_tar], "builder/mac/generic/")
|
||||
utils.set_summary("builder deploy", ret)
|
||||
make_tar()
|
||||
make_wheel()
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def make_linux():
|
||||
utils.set_cwd("document-builder-package")
|
||||
|
||||
utils.log_h2("builder build")
|
||||
make_args = [t["make"] for t in branding.builder_make_targets]
|
||||
def make_tar():
|
||||
utils.log_h2("builder tar build")
|
||||
make_args = ["tar"]
|
||||
if common.platform == "darwin_arm64":
|
||||
make_args += ["-e", "UNAME_M=arm64"]
|
||||
if common.platform == "linux_aarch64":
|
||||
make_args += ["-e", "UNAME_M=aarch64"]
|
||||
if not branding.onlyoffice:
|
||||
make_args += ["-e", "BRANDING_DIR=../" + common.branding + "/document-builder-package"]
|
||||
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
|
||||
utils.set_summary("builder build", ret)
|
||||
utils.set_summary("builder tar build", ret)
|
||||
|
||||
if common.deploy:
|
||||
for t in branding.builder_make_targets:
|
||||
utils.log_h2("builder " + t["make"] + " deploy")
|
||||
ret = s3_upload(utils.glob_path(t["src"]), t["dst"])
|
||||
utils.set_summary("builder " + t["make"] + " deploy", ret)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
utils.log_h2("builder tar deploy")
|
||||
if utils.is_macos():
|
||||
s3_dest = "builder/mac/generic/"
|
||||
elif utils.is_linux():
|
||||
s3_dest = "builder/linux/generic/"
|
||||
ret = s3_upload(utils.glob_path("tar/*.tar.xz"), s3_dest)
|
||||
utils.set_summary("builder tar deploy", ret)
|
||||
return
|
||||
|
||||
def make_wheel():
|
||||
platform_tags = {
|
||||
"windows_x64": "win_amd64",
|
||||
"windows_x86": "win32",
|
||||
"darwin_arm64": "macosx_11_0_arm64",
|
||||
"darwin_x86_64": "macosx_10_9_x86_64",
|
||||
"linux_x86_64": "manylinux_2_23_x86_64",
|
||||
"linux_aarch64": "manylinux_2_23_aarch64"
|
||||
}
|
||||
|
||||
if not common.platform in platform_tags: return
|
||||
|
||||
utils.log_h2("builder python wheel build")
|
||||
|
||||
builder_dir = "build"
|
||||
if utils.is_linux():
|
||||
builder_dir = "build/opt/onlyoffice/documentbuilder"
|
||||
|
||||
utils.delete_dir("python")
|
||||
utils.copy_dir("../onlyoffice/build_tools/packaging/docbuilder/resources", "python")
|
||||
utils.copy_dir(builder_dir, "python/docbuilder/lib")
|
||||
|
||||
desktop_dir = "../desktop-apps/macos/build/ONLYOFFICE.app/Contents/Resources/converter"
|
||||
if utils.is_macos() and "desktop" in common.targets and utils.is_exist(desktop_dir):
|
||||
for f in utils.glob_path(desktop_dir + "/*.dylib") + [desktop_dir + "/x2t"]:
|
||||
utils.copy_file(f, builder_dir + "/" + utils.get_basename(f))
|
||||
|
||||
old_cwd = utils.get_cwd()
|
||||
utils.set_cwd("python/docbuilder")
|
||||
|
||||
if not utils.is_file("docbuilder.py"):
|
||||
utils.copy_file("lib/docbuilder.py", "docbuilder.py")
|
||||
# fix docbuilder.py
|
||||
content = ""
|
||||
with open("docbuilder.py", "r") as file:
|
||||
content = file.read()
|
||||
old_line = "builder_path = os.path.dirname(os.path.realpath(__file__))"
|
||||
new_line = "builder_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), \"lib\")"
|
||||
content = content.replace(old_line, new_line)
|
||||
with open("docbuilder.py", "w") as file:
|
||||
file.write(content)
|
||||
|
||||
# remove unnecessary files
|
||||
utils.set_cwd("lib")
|
||||
utils.delete_dir("include")
|
||||
utils.delete_file("build.date")
|
||||
utils.delete_file("docbuilder.jar")
|
||||
utils.delete_file("docbuilder.py")
|
||||
if utils.is_windows():
|
||||
utils.delete_file("doctrenderer.lib")
|
||||
utils.delete_file("docbuilder.com.dll")
|
||||
utils.delete_file("docbuilder.net.dll")
|
||||
utils.delete_file("docbuilder.jni.dll")
|
||||
elif utils.is_macos():
|
||||
utils.delete_file("libdocbuilder.jni.dylib")
|
||||
elif utils.is_linux():
|
||||
utils.delete_file("libdocbuilder.jni.so")
|
||||
|
||||
utils.set_env("DOCBUILDER_VERSION", common.version + "." + common.build)
|
||||
platform = "linux_64"
|
||||
utils.set_cwd("../..")
|
||||
plat_name = platform_tags[common.platform]
|
||||
ret = utils.sh("python setup.py bdist_wheel --plat-name " + plat_name + " --python-tag py2.py3", verbose=True)
|
||||
utils.set_summary("builder python wheel build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("builder python wheel deploy")
|
||||
if utils.is_windows():
|
||||
s3_dest = "builder/win/python/"
|
||||
elif utils.is_macos():
|
||||
s3_dest = "builder/mac/python/"
|
||||
elif utils.is_linux():
|
||||
s3_dest = "builder/linux/python/"
|
||||
ret = s3_upload(utils.glob_path("dist/*.whl"), s3_dest)
|
||||
utils.set_summary("builder python wheel deploy", ret)
|
||||
|
||||
utils.set_cwd(old_cwd)
|
||||
|
||||
return
|
||||
|
||||
@ -3,14 +3,14 @@
|
||||
platformPrefixes = {
|
||||
"windows_x64": "win_64",
|
||||
"windows_x86": "win_32",
|
||||
"windows_arm64": "win_arm64",
|
||||
"windows_x64_xp": "win_64_xp",
|
||||
"windows_x86_xp": "win_32_xp",
|
||||
"darwin_x86_64": "mac_64",
|
||||
"darwin_arm64": "mac_arm64",
|
||||
"darwin_x86_64": "mac_64",
|
||||
"darwin_x86_64_v8": "mac_64",
|
||||
"linux_x86_64": "linux_64",
|
||||
"linux_aarch64": "linux_arm64",
|
||||
"linux_x86_64_cef": "linux_64",
|
||||
}
|
||||
|
||||
out_dir = "build_tools/out"
|
||||
|
||||
@ -10,47 +10,37 @@ def make():
|
||||
utils.log("Unsupported host OS")
|
||||
return
|
||||
if common.deploy:
|
||||
make_core()
|
||||
make_archive()
|
||||
return
|
||||
|
||||
def make_core():
|
||||
prefix = common.platformPrefixes[common.platform]
|
||||
company = branding.company_name.lower()
|
||||
repos = {
|
||||
"windows_x64": { "repo": "windows", "arch": "x64", "version": common.version + "." + common.build },
|
||||
"windows_x86": { "repo": "windows", "arch": "x86", "version": common.version + "." + common.build },
|
||||
"darwin_x86_64": { "repo": "mac", "arch": "x64", "version": common.version + "-" + common.build },
|
||||
"darwin_arm64": { "repo": "mac", "arch": "arm", "version": common.version + "-" + common.build },
|
||||
"linux_x86_64": { "repo": "linux", "arch": "x64", "version": common.version + "-" + common.build },
|
||||
}
|
||||
repo = repos[common.platform]
|
||||
branch = utils.get_env("BRANCH_NAME")
|
||||
core_7z = utils.get_path("build_tools/out/%s/%s/core.7z" % (prefix, company))
|
||||
dest_version = "%s/core/%s/%s/%s" % (repo["repo"], branch, repo["version"], repo["arch"])
|
||||
dest_latest = "%s/core/%s/%s/%s" % (repo["repo"], branch, "latest", repo["arch"])
|
||||
def make_archive():
|
||||
utils.set_cwd(utils.get_path(
|
||||
"build_tools/out/" + common.prefix + "/" + branding.company_name.lower()))
|
||||
|
||||
if branch is None:
|
||||
utils.log_err("BRANCH_NAME variable is undefined")
|
||||
utils.set_summary("core deploy", False)
|
||||
return
|
||||
if not utils.is_file(core_7z):
|
||||
utils.log_err("file not exist: " + core_7z)
|
||||
utils.set_summary("core deploy", False)
|
||||
return
|
||||
utils.log_h2("core archive build")
|
||||
utils.delete_file("core.7z")
|
||||
args = ["7z", "a", "-y", "core.7z", "./core/*"]
|
||||
if utils.is_windows():
|
||||
ret = utils.cmd(*args, verbose=True)
|
||||
else:
|
||||
ret = utils.sh(" ".join(args), verbose=True)
|
||||
utils.set_summary("core archive build", ret)
|
||||
|
||||
utils.log_h2("core deploy")
|
||||
utils.log_h2("core archive deploy")
|
||||
dest = "core-" + common.prefix.replace("_","-") + ".7z"
|
||||
dest_latest = "archive/%s/latest/%s" % (common.branch, dest)
|
||||
dest_version = "archive/%s/%s/%s" % (common.branch, common.build, dest)
|
||||
ret = utils.s3_upload(
|
||||
core_7z,
|
||||
"s3://" + branding.s3_bucket + "/" + dest_version + "/core.7z")
|
||||
"core.7z", "s3://" + branding.s3_bucket + "/" + dest_version)
|
||||
utils.set_summary("core archive deploy", ret)
|
||||
if ret:
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_version + "/core.7z")
|
||||
utils.add_deploy_data(dest_version + "/core.7z")
|
||||
ret = utils.s3_sync(
|
||||
"s3://" + branding.s3_bucket + "/" + dest_version + "/",
|
||||
"s3://" + branding.s3_bucket + "/" + dest_latest + "/",
|
||||
delete=True)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_latest + "/core.7z")
|
||||
utils.set_summary("core deploy", ret)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_version)
|
||||
utils.s3_copy(
|
||||
"s3://" + branding.s3_bucket + "/" + dest_version,
|
||||
"s3://" + branding.s3_bucket + "/" + dest_latest)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + dest_latest)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def deploy_closuremaps_sdkjs(license):
|
||||
@ -74,7 +64,6 @@ def deploy_closuremaps_sdkjs(license):
|
||||
ret &= upload
|
||||
if upload:
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
utils.add_deploy_data(key)
|
||||
utils.set_summary("sdkjs closure maps %s deploy" % license, ret)
|
||||
return
|
||||
|
||||
@ -100,6 +89,5 @@ def deploy_closuremaps_webapps(license):
|
||||
ret &= upload
|
||||
if upload:
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
utils.add_deploy_data(key)
|
||||
utils.set_summary("web-apps closure maps %s deploy" % license, ret)
|
||||
return
|
||||
|
||||
@ -26,7 +26,6 @@ def s3_upload(files, dst):
|
||||
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
|
||||
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
|
||||
if upload:
|
||||
utils.add_deploy_data(key)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
ret &= upload
|
||||
return ret
|
||||
@ -36,7 +35,7 @@ def s3_upload(files, dst):
|
||||
#
|
||||
|
||||
def make_windows():
|
||||
global package_name, package_version, arch, xp, suffix
|
||||
global package_name, package_version, arch, xp
|
||||
utils.set_cwd("desktop-apps\\win-linux\\package\\windows")
|
||||
|
||||
package_name = branding.desktop_package_name
|
||||
@ -45,10 +44,10 @@ def make_windows():
|
||||
"windows_x64": "x64",
|
||||
"windows_x64_xp": "x64",
|
||||
"windows_x86": "x86",
|
||||
"windows_x86_xp": "x86"
|
||||
"windows_x86_xp": "x86",
|
||||
"windows_arm64": "arm64"
|
||||
}[common.platform]
|
||||
xp = common.platform.endswith("_xp")
|
||||
suffix = arch + ("-xp" if xp else "")
|
||||
|
||||
if common.clean:
|
||||
utils.log_h2("desktop clean")
|
||||
@ -60,132 +59,130 @@ def make_windows():
|
||||
utils.delete_files("*.zip")
|
||||
utils.delete_files("data\\*.exe")
|
||||
|
||||
make_prepare()
|
||||
make_zip()
|
||||
make_inno()
|
||||
make_advinst()
|
||||
if not xp:
|
||||
make_prepare()
|
||||
make_zip()
|
||||
if branding.onlyoffice:
|
||||
make_inno()
|
||||
make_inno("standalone")
|
||||
if arch != "arm64":
|
||||
make_inno("update")
|
||||
make_advinst()
|
||||
|
||||
make_prepare("commercial")
|
||||
make_zip("commercial")
|
||||
make_inno("commercial")
|
||||
make_advinst("commercial")
|
||||
else:
|
||||
make_prepare("xp")
|
||||
make_zip("xp")
|
||||
make_inno("xp")
|
||||
# Disable build online installer
|
||||
# if common.platform == "windows_x86_xp":
|
||||
# make_online()
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def make_prepare():
|
||||
def make_prepare(edition = "opensource"):
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
"-Arch", arch,
|
||||
"-Target", edition,
|
||||
"-CompanyName", branding.company_name
|
||||
]
|
||||
if xp:
|
||||
args += ["-Target", "xp"]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
|
||||
utils.log_h2("desktop prepare")
|
||||
utils.log_h2("desktop prepare " + edition)
|
||||
ret = utils.ps1("make.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop prepare", ret)
|
||||
utils.set_summary("desktop prepare " + edition, ret)
|
||||
return
|
||||
|
||||
def make_zip():
|
||||
zip_file = "%s-%s-%s.zip" % (package_name, package_version, suffix)
|
||||
def make_zip(edition = "opensource"):
|
||||
if edition == "commercial": zip_file = "%s-Enterprise-%s-%s.zip"
|
||||
elif edition == "xp": zip_file = "%s-XP-%s-%s.zip"
|
||||
else: zip_file = "%s-%s-%s.zip"
|
||||
zip_file = zip_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
"-Arch", arch,
|
||||
"-Target", edition,
|
||||
"-CompanyName", branding.company_name
|
||||
]
|
||||
if xp:
|
||||
args += ["-Target", "xp"]
|
||||
# if common.sign:
|
||||
# args += ["-Sign"]
|
||||
|
||||
utils.log_h2("desktop zip build")
|
||||
utils.log_h2("desktop zip " + edition + " build")
|
||||
ret = utils.ps1("make_zip.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop zip build", ret)
|
||||
utils.set_summary("desktop zip " + edition + " build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("desktop zip deploy")
|
||||
utils.log_h2("desktop zip " + edition + " deploy")
|
||||
ret = s3_upload([zip_file], "desktop/win/generic/")
|
||||
utils.set_summary("desktop zip deploy", ret)
|
||||
utils.set_summary("desktop zip " + edition + " deploy", ret)
|
||||
return
|
||||
|
||||
def make_inno():
|
||||
inno_file = "%s-%s-%s.exe" % (package_name, package_version, suffix)
|
||||
inno_sa_file = "%s-Standalone-%s-%s.exe" % (package_name, package_version, suffix)
|
||||
inno_update_file = "%s-Update-%s-%s.exe" % (package_name, package_version, suffix)
|
||||
update_wrapper = not (hasattr(branding, 'desktop_updates_skip_iss_wrapper') and branding.desktop_updates_skip_iss_wrapper)
|
||||
def make_inno(edition = "opensource"):
|
||||
if edition == "commercial": inno_file = "%s-Enterprise-%s-%s.exe"
|
||||
elif edition == "standalone": inno_file = "%s-Standalone-%s-%s.exe"
|
||||
elif edition == "update": inno_file = "%s-Update-%s-%s.exe"
|
||||
elif edition == "xp": inno_file = "%s-XP-%s-%s.exe"
|
||||
else: inno_file = "%s-%s-%s.exe"
|
||||
inno_file = inno_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
"-Arch", arch,
|
||||
"-Target", edition
|
||||
]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
|
||||
utils.log_h2("desktop inno build")
|
||||
if xp:
|
||||
ret = utils.ps1("make_inno.ps1", args + ["-Target", "xp"], verbose=True)
|
||||
else:
|
||||
ret = utils.ps1("make_inno.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop inno build", ret)
|
||||
args += ["-TimestampServer", "http://timestamp.comodoca.com/authenticode"]
|
||||
|
||||
if branding.onlyoffice and not xp:
|
||||
utils.log_h2("desktop inno standalone")
|
||||
ret = utils.ps1("make_inno.ps1", args + ["-Target", "standalone"], verbose=True)
|
||||
utils.set_summary("desktop inno standalone build", ret)
|
||||
|
||||
if update_wrapper:
|
||||
utils.log_h2("desktop inno update build")
|
||||
if xp:
|
||||
ret = utils.ps1("make_inno.ps1", args + ["-Target", "xp_update"], verbose=True)
|
||||
else:
|
||||
ret = utils.ps1("make_inno.ps1", args + ["-Target", "update"], verbose=True)
|
||||
utils.set_summary("desktop inno update build", ret)
|
||||
|
||||
if common.deploy:
|
||||
utils.log_h2("desktop inno deploy")
|
||||
ret = s3_upload([inno_file], "desktop/win/inno/")
|
||||
utils.set_summary("desktop inno deploy", ret)
|
||||
|
||||
if branding.onlyoffice and not xp:
|
||||
utils.log_h2("desktop inno standalone deploy")
|
||||
ret = s3_upload([inno_sa_file], "desktop/win/inno/")
|
||||
utils.set_summary("desktop inno standalone deploy", ret)
|
||||
|
||||
utils.log_h2("desktop inno update deploy")
|
||||
if utils.is_file(inno_update_file):
|
||||
ret = s3_upload([inno_update_file], "desktop/win/inno/")
|
||||
elif utils.is_file(inno_file):
|
||||
ret = s3_upload([inno_file], "desktop/win/inno/" + inno_update_file)
|
||||
else:
|
||||
ret = False
|
||||
utils.set_summary("desktop inno update deploy", ret)
|
||||
|
||||
changes_dir = common.workspace_dir + "\\" \
|
||||
+ utils.get_path(branding.desktop_changes_dir) + "\\" + common.version
|
||||
if common.platform == "windows_x64" and \
|
||||
common.deploy and \
|
||||
utils.glob_path(changes_dir + "\\*.html"):
|
||||
utils.log_h2("desktop changelog deploy")
|
||||
ret = s3_upload(
|
||||
utils.glob_path(changes_dir + "\\*.html"),
|
||||
"desktop/win/update/%s/%s/" % (common.version, common.build))
|
||||
utils.set_summary("desktop changelog deploy", ret)
|
||||
return
|
||||
|
||||
def make_advinst():
|
||||
if not common.platform in ["windows_x64", "windows_x86"]:
|
||||
return
|
||||
advinst_file = "%s-%s-%s.msi" % (package_name, package_version, suffix)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch
|
||||
]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
|
||||
utils.log_h2("desktop advinst build")
|
||||
ret = utils.ps1("make_advinst.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop advinst build", ret)
|
||||
utils.log_h2("desktop inno " + edition + " build")
|
||||
ret = utils.ps1("make_inno.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop inno " + edition + " build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("desktop advinst deploy")
|
||||
utils.log_h2("desktop inno " + edition + " deploy")
|
||||
ret = s3_upload([inno_file], "desktop/win/inno/")
|
||||
utils.set_summary("desktop inno " + edition + " deploy", ret)
|
||||
return
|
||||
|
||||
def make_advinst(edition = "opensource"):
|
||||
if edition == "commercial": advinst_file = "%s-Enterprise-%s-%s.msi"
|
||||
else: advinst_file = "%s-%s-%s.msi"
|
||||
advinst_file = advinst_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch,
|
||||
"-Target", edition
|
||||
]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
|
||||
utils.log_h2("desktop advinst " + edition + " build")
|
||||
ret = utils.ps1("make_advinst.ps1", args, verbose=True)
|
||||
utils.set_summary("desktop advinst " + edition + " build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("desktop advinst " + edition + " deploy")
|
||||
ret = s3_upload([advinst_file], "desktop/win/advinst/")
|
||||
utils.set_summary("desktop advinst deploy", ret)
|
||||
utils.set_summary("desktop advinst " + edition + " deploy", ret)
|
||||
return
|
||||
|
||||
def make_online():
|
||||
online_file = utils.glob_file("OnlineInstaller-" + package_version + "*.exe")
|
||||
utils.log_h2("desktop online installer build")
|
||||
ret = utils.is_file(online_file)
|
||||
utils.set_summary("desktop online installer build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("desktop online installer deploy")
|
||||
ret = s3_upload([online_file], "desktop/win/online/")
|
||||
utils.set_summary("desktop online installer deploy", ret)
|
||||
return
|
||||
|
||||
#
|
||||
@ -194,7 +191,7 @@ def make_advinst():
|
||||
|
||||
def make_macos():
|
||||
global package_name, build_dir, branding_dir, updates_dir, changes_dir, \
|
||||
suffix, lane, scheme, released_updates_dir
|
||||
suffix, lane, scheme, source_dir, released_updates_dir
|
||||
package_name = branding.desktop_package_name
|
||||
build_dir = branding.desktop_build_dir
|
||||
branding_dir = branding.desktop_branding_dir
|
||||
@ -259,32 +256,34 @@ def make_macos():
|
||||
dmg = make_dmg()
|
||||
if dmg and sparkle_updates:
|
||||
make_sparkle_updates()
|
||||
if common.platform != "darwin_x86_64_v8":
|
||||
make_dmg("commercial")
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
def make_dmg():
|
||||
utils.log_h2("desktop dmg build")
|
||||
utils.log_h3(scheme)
|
||||
def make_dmg(target = "opensource"):
|
||||
utils.log_h2("desktop dmg " + target + " build")
|
||||
utils.log_h3("build/" + package_name + ".app")
|
||||
dmg = utils.sh(
|
||||
"bundler exec fastlane " + lane + " skip_git_bump:true",
|
||||
verbose=True
|
||||
)
|
||||
utils.set_summary("desktop dmg build", dmg)
|
||||
args = ["bundler", "exec", "fastlane", lane, "skip_git_bump:true"]
|
||||
if target == "commercial":
|
||||
args += ["edition:Enterprise"]
|
||||
dmg = utils.sh(" ".join(args), verbose=True)
|
||||
utils.set_summary("desktop dmg " + target + " build", dmg)
|
||||
|
||||
if common.deploy and dmg:
|
||||
utils.log_h2("desktop dmg deploy")
|
||||
utils.log_h2("desktop dmg " + target + " deploy")
|
||||
ret = s3_upload(
|
||||
utils.glob_path("build/*.dmg"),
|
||||
"desktop/mac/%s/%s/%s/" % (suffix, common.version, common.build))
|
||||
utils.set_summary("desktop dmg deploy", ret)
|
||||
|
||||
utils.log_h2("desktop zip deploy")
|
||||
if common.deploy and dmg and target != "commercial":
|
||||
utils.log_h2("desktop zip " + target + " deploy")
|
||||
ret = s3_upload(
|
||||
["build/%s-%s.zip" % (scheme, common.version)],
|
||||
"desktop/mac/%s/%s/%s/" % (suffix, common.version, common.build))
|
||||
utils.set_summary("desktop zip deploy", ret)
|
||||
utils.set_summary("desktop zip " + target + " deploy", ret)
|
||||
return dmg
|
||||
|
||||
def make_sparkle_updates():
|
||||
@ -294,11 +293,17 @@ def make_sparkle_updates():
|
||||
macos_zip = "build/" + zip_filename + ".zip"
|
||||
utils.create_dir(updates_dir)
|
||||
utils.copy_file(macos_zip, updates_dir)
|
||||
utils.copy_dir_content(released_updates_dir, updates_dir, ".zip")
|
||||
utils.sh(
|
||||
"ls -1t " + released_updates_dir + "/*.zip" \
|
||||
+ " | head -n 3" \
|
||||
+ " | while read f; do cp -fv \"$f\" " + updates_dir + "/; done",
|
||||
verbose=True)
|
||||
|
||||
for file in utils.glob_path(changes_dir + "/" + common.version + "/*.html"):
|
||||
filename = utils.get_basename(file).replace("changes", zip_filename)
|
||||
utils.copy_file(file, updates_dir + "/" + filename)
|
||||
for ext in [".html", ".ru.html"]:
|
||||
changes_src = changes_dir + "/" + common.version + "/changes" + ext
|
||||
changes_dst = updates_dir + "/" + zip_filename + ext
|
||||
if not utils.copy_file(changes_src, changes_dst):
|
||||
utils.write_file(changes_dst, "<!DOCTYPE html>placeholder")
|
||||
|
||||
sparkle_base_url = "%s/%s/updates/" % (branding.sparkle_base_url, suffix)
|
||||
ret = utils.sh(
|
||||
@ -328,20 +333,25 @@ def make_sparkle_updates():
|
||||
def make_linux():
|
||||
utils.set_cwd("desktop-apps/win-linux/package/linux")
|
||||
|
||||
utils.log_h2("desktop build")
|
||||
make_args = [t["make"] for t in branding.desktop_make_targets]
|
||||
if common.platform == "linux_aarch64":
|
||||
make_args += ["-e", "UNAME_M=aarch64"]
|
||||
if not branding.onlyoffice:
|
||||
make_args += ["-e", "BRANDING_DIR=../../../../" + common.branding + "/desktop-apps/win-linux/package/linux"]
|
||||
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
|
||||
utils.set_summary("desktop build", ret)
|
||||
for edition in ["opensource", "commercial"]:
|
||||
utils.log_h2("desktop " + edition + " build")
|
||||
make_args = [t["make"] for t in branding.desktop_make_targets]
|
||||
if edition == "commercial":
|
||||
make_args += ["-e", "PACKAGE_EDITION=commercial"]
|
||||
if common.platform == "linux_aarch64":
|
||||
make_args += ["-e", "UNAME_M=aarch64"]
|
||||
if not branding.onlyoffice:
|
||||
make_args += ["-e", "BRANDING_DIR=../../../../" + common.branding + "/desktop-apps/win-linux/package/linux"]
|
||||
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
|
||||
utils.set_summary("desktop " + edition + " build", ret)
|
||||
|
||||
if common.deploy:
|
||||
for t in branding.desktop_make_targets:
|
||||
utils.log_h2("desktop " + t["make"] + " deploy")
|
||||
ret = s3_upload(utils.glob_path(t["src"]), t["dst"])
|
||||
utils.set_summary("desktop " + t["make"] + " deploy", ret)
|
||||
if common.deploy:
|
||||
for t in branding.desktop_make_targets:
|
||||
utils.log_h2("desktop " + edition + " " + t["make"] + " deploy")
|
||||
ret = s3_upload(
|
||||
[i for i in utils.glob_path(t["src"]) if "enterprise-help" not in i],
|
||||
t["dst"])
|
||||
utils.set_summary("desktop " + edition + " " + t["make"] + " deploy", ret)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
|
||||
@ -31,7 +31,6 @@ def make_mobile():
|
||||
key = "mobile/android/" + zip_file
|
||||
ret = utils.s3_upload(zip_file, "s3://" + branding.s3_bucket + "/" + key)
|
||||
if ret:
|
||||
utils.add_deploy_data(key)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
utils.set_summary("mobile deploy", ret)
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ def s3_upload(files, dst):
|
||||
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
|
||||
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
|
||||
if upload:
|
||||
utils.add_deploy_data(key)
|
||||
utils.log("URL: " + branding.s3_base_url + "/" + key)
|
||||
ret &= upload
|
||||
return ret
|
||||
@ -37,10 +36,13 @@ def make_windows(edition):
|
||||
|
||||
utils.log_h2("server " + edition + " build")
|
||||
ret = utils.cmd("make", "clean", verbose=True)
|
||||
args = ["-e", "PRODUCT_NAME=" + product_name]
|
||||
if edition == "prerequisites":
|
||||
make_args = ["exe-pr"]
|
||||
else:
|
||||
make_args = ["exe", "-e", "PRODUCT_NAME=" + product_name]
|
||||
if not branding.onlyoffice:
|
||||
args += ["-e", "BRANDING_DIR=../" + common.branding + "/document-server-package"]
|
||||
ret &= utils.cmd("make", "packages", *args, verbose=True)
|
||||
make_args += ["-e", "BRANDING_DIR=../" + common.branding + "/document-server-package"]
|
||||
ret &= utils.cmd("make", *make_args, verbose=True)
|
||||
utils.set_summary("server " + edition + " build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
|
||||
@ -266,11 +266,6 @@ def set_summary(target, status):
|
||||
common.summary.append({target: status})
|
||||
return
|
||||
|
||||
def add_deploy_data(key):
|
||||
with open(common.deploy_data, 'a+') as f:
|
||||
f.write(key + "\n")
|
||||
return
|
||||
|
||||
def cmd(*args, **kwargs):
|
||||
if kwargs.get("verbose"):
|
||||
log("- cmd:")
|
||||
@ -385,15 +380,13 @@ def s3_upload(src, dst, **kwargs):
|
||||
ret = sh(" ".join(args), verbose=True)
|
||||
return ret
|
||||
|
||||
def s3_sync(src, dst, **kwargs):
|
||||
def s3_copy(src, dst, **kwargs):
|
||||
args = ["aws"]
|
||||
if kwargs.get("endpoint_url"):
|
||||
args += ["--endpoint-url", kwargs["endpoint_url"]]
|
||||
args += ["s3", "sync", "--no-progress"]
|
||||
args += ["s3", "cp", "--no-progress"]
|
||||
if kwargs.get("acl"):
|
||||
args += ["--acl", kwargs["acl"]]
|
||||
if kwargs.get("delete") and kwargs["delete"]:
|
||||
args += ["--delete"]
|
||||
args += [src, dst]
|
||||
if is_windows():
|
||||
ret = cmd(*args, verbose=True)
|
||||
|
||||
@ -25,11 +25,11 @@ def get_j_num():
|
||||
|
||||
def check_support_platform(platform):
|
||||
qt_dir = base.qt_setup(platform)
|
||||
if not base.is_file(qt_dir + "/bin/qmake") and not base.is_file(qt_dir + "/bin/qmake.exe"):
|
||||
if not base.is_file(qt_dir + "/bin/qmake") and not base.is_file(qt_dir + "/bin/qmake.exe") and not base.is_file(qt_dir + "/bin/qmake.bat"):
|
||||
return False
|
||||
return True
|
||||
|
||||
def make(platform, project, qmake_config_addon=""):
|
||||
def make(platform, project, qmake_config_addon="", is_no_errors=False):
|
||||
# check platform
|
||||
if not check_support_platform(platform):
|
||||
print("THIS PLATFORM IS NOT SUPPORTED")
|
||||
@ -91,16 +91,32 @@ def make(platform, project, qmake_config_addon=""):
|
||||
build_params = ["-nocache", file_pro] + base.qt_config_as_param(config_param) + qmake_addon
|
||||
|
||||
qmake_app = qt_dir + "/bin/qmake"
|
||||
|
||||
# non windows platform
|
||||
if not base.is_windows():
|
||||
base.cmd(qmake_app, build_params)
|
||||
if base.is_file(qt_dir + "/onlyoffice_qt.conf"):
|
||||
build_params.append("-qtconf")
|
||||
build_params.append(qt_dir + "/onlyoffice_qt.conf")
|
||||
if "1" == config.option("use-clang"):
|
||||
build_params.append("-spec")
|
||||
build_params.append("linux-clang-libc++")
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
os.environ['QMAKE_CUSTOM_SYSROOT'] = config.option("sysroot")
|
||||
os.environ['PKG_CONFIG_PATH'] = config.get_custom_sysroot_lib() + "/pkgconfig"
|
||||
|
||||
base.cmd_exe(qmake_app, build_params)
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
base.set_sysroot_env()
|
||||
|
||||
base.correct_makefile_after_qmake(platform, makefile)
|
||||
if ("1" == config.option("clean")):
|
||||
base.cmd_and_return_cwd("make", clean_params, True)
|
||||
base.cmd_and_return_cwd("make", distclean_params, True)
|
||||
base.cmd(qmake_app, build_params)
|
||||
base.correct_makefile_after_qmake(platform, makefile)
|
||||
base.cmd_and_return_cwd("make", ["-f", makefile] + get_j_num())
|
||||
base.cmd_and_return_cwd("make", ["-f", makefile] + get_j_num(), is_no_errors)
|
||||
else:
|
||||
config_params_array = base.qt_config_as_param(config_param)
|
||||
config_params_string = ""
|
||||
@ -110,12 +126,22 @@ def make(platform, project, qmake_config_addon=""):
|
||||
if ("" != qmake_addon_string):
|
||||
qmake_addon_string = " " + qmake_addon_string
|
||||
|
||||
vcvarsall_arch = "x64"
|
||||
if base.platform_is_32(platform):
|
||||
vcvarsall_arch = "x86"
|
||||
if (platform == "win_arm64"):
|
||||
vcvarsall_arch = "x64_arm64"
|
||||
|
||||
qmake_env_addon = base.get_env("QT_QMAKE_ADDON")
|
||||
if (qmake_env_addon != ""):
|
||||
qmake_env_addon += " "
|
||||
|
||||
qmake_bat = []
|
||||
qmake_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + ("x86" if base.platform_is_32(platform) else "x64"))
|
||||
qmake_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + vcvarsall_arch)
|
||||
qmake_addon_string = ""
|
||||
if ("" != config.option("qmake_addon")):
|
||||
qmake_addon_string = " " + (" ").join(["\"" + addon + "\"" for addon in qmake_addon])
|
||||
qmake_bat.append("call \"" + qmake_app + "\" -nocache " + file_pro + config_params_string + qmake_addon_string)
|
||||
qmake_bat.append("call \"" + qmake_app + "\" -nocache " + qmake_env_addon + file_pro + config_params_string + qmake_addon_string)
|
||||
if ("1" == config.option("clean")):
|
||||
qmake_bat.append("call nmake " + " ".join(clean_params))
|
||||
qmake_bat.append("call nmake " + " ".join(distclean_params))
|
||||
@ -123,7 +149,7 @@ def make(platform, project, qmake_config_addon=""):
|
||||
if ("0" != config.option("multiprocess")):
|
||||
qmake_bat.append("set CL=/MP")
|
||||
qmake_bat.append("call nmake -f " + makefile)
|
||||
base.run_as_bat(qmake_bat)
|
||||
base.run_as_bat(qmake_bat, is_no_errors)
|
||||
|
||||
if (base.is_file(stash_file)):
|
||||
base.delete_file(stash_file)
|
||||
|
||||
@ -13,7 +13,7 @@ def writeFile(path, content):
|
||||
if (os.path.isfile(path)):
|
||||
os.remove(path)
|
||||
|
||||
with open(path, "w") as file:
|
||||
with open(path, "w", encoding='utf-8') as file:
|
||||
file.write(content)
|
||||
return
|
||||
|
||||
@ -160,6 +160,12 @@ class EditorApi(object):
|
||||
editors_support = decoration[index_type_editors:index_type_editors_end]
|
||||
if -1 == editors_support.find(self.type):
|
||||
return
|
||||
|
||||
decoration = "\n".join(
|
||||
line for line in decoration.splitlines()
|
||||
if "@typeofeditors" not in line and "@see" not in line
|
||||
)
|
||||
|
||||
# optimizations for first file
|
||||
if 0 == self.numfile:
|
||||
self.records.append(decoration + "\n" + code + "\n")
|
||||
@ -208,7 +214,7 @@ if __name__ == "__main__":
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default="../../../onlyoffice.github.io\sdkjs-plugins\content\macros\libs/" # Default value
|
||||
default="../../../web-apps/vendor/monaco/libs/" # Default value
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -217,7 +223,7 @@ if __name__ == "__main__":
|
||||
if True == os.path.isdir(args.destination):
|
||||
shutil.rmtree(args.destination, ignore_errors=True)
|
||||
os.mkdir(args.destination)
|
||||
convert_to_interface(["word/apiBuilder.js"], "word")
|
||||
convert_to_interface(["word/apiBuilder.js", "../sdkjs-forms/apiBuilder.js"], "word")
|
||||
convert_to_interface(["word/apiBuilder.js", "slide/apiBuilder.js"], "slide")
|
||||
convert_to_interface(["word/apiBuilder.js", "slide/apiBuilder.js", "cell/apiBuilder.js"], "cell")
|
||||
os.chdir(old_cur)
|
||||
|
||||
@ -1,57 +1,138 @@
|
||||
|
||||
# Documentation Generation Guide
|
||||
|
||||
This guide explains how to generate documentation for Onlyoffice API using the provided Python scripts, `generate_docs_json.py` and `generate_docs_md.py`. These scripts are used to create JSON and Markdown documentation for the `apiBuilder.js` files from the word, cell, and slide editors.
|
||||
This guide explains how to generate documentation for Onlyoffice Builder
|
||||
and Plugins (Methods/Events) API using the following Python scripts:
|
||||
|
||||
## Prerequisites
|
||||
- `office-api/generate_docs_json.py`
|
||||
- `office-api/generate_docs_md.py`
|
||||
- `plugins/generate_docs_methods_json.py`
|
||||
- `plugins/generate_docs_methods_md.py`
|
||||
- `plugins/generate_docs_events_json.py`
|
||||
- `plugins/generate_docs_events_md.py`
|
||||
|
||||
1. **Node.js and npm**: Ensure you have Node.js and npm installed on your machine. You can download them from [Node.js official website](https://nodejs.org/).
|
||||
## Requirements
|
||||
|
||||
2. **jsdoc**: The scripts use `jsdoc` to generate documentation. Install it using npm:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
```bash
|
||||
Node.js v20 and above
|
||||
Python v3.10 and above
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ONLYOFFICE/build_tools.git
|
||||
cd build_tools/scripts/sdkjs_common/jsdoc
|
||||
npm install
|
||||
```
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### `generate_docs_json.py`
|
||||
### `office-api/generate_docs_json.py`
|
||||
|
||||
This script generates JSON documentation based on the `apiBuilder.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_json.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the JSON documentation will be saved. If not specified, the default path is `Onlyoffice/sdkjs/deploy/api_builder/json`.
|
||||
- `output_path` (optional): The directory where the JSON documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api-declarations/office-js-api`.
|
||||
|
||||
### `generate_docs_md.py`
|
||||
### `office-api/generate_docs_md.py`
|
||||
|
||||
This script generates Markdown documentation from the `apiBuilder.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_md.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the Markdown documentation will be saved. If not specified, the default path is `Onlyoffice/office-js-api`.
|
||||
- `output_path` (optional): The directory where the Markdown documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api/`.
|
||||
|
||||
### `plugins/generate_docs_methods_json.py`
|
||||
|
||||
This script generates JSON documentation based on the `api_plugins.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_methods_json.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the JSON documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api-declarations/office-js-api-plugins`.
|
||||
|
||||
### `plugins/generate_docs_events_json.py`
|
||||
|
||||
This script generates JSON documentation based on the `plugin-events.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_events_json.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the JSON documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api-declarations/office-js-api-plugins`.
|
||||
|
||||
### `plugins/generate_docs_methods_md.py`
|
||||
|
||||
This script generates Markdown documentation from the `api_plugins.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_methods_md.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the Markdown documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api/`.
|
||||
|
||||
### `plugins/generate_docs_events_md.py`
|
||||
|
||||
This script generates Markdown documentation from the `plugin-events.js` files.
|
||||
|
||||
- **Usage**:
|
||||
|
||||
```bash
|
||||
python generate_docs_events_md.py output_path
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `output_path` (optional): The directory where the Markdown documentation
|
||||
will be saved. If not specified, the default path is
|
||||
`../../../../office-js-api/`.
|
||||
|
||||
## Example
|
||||
|
||||
To generate JSON documentation with the default output path:
|
||||
|
||||
```bash
|
||||
python generate_docs_json.py /path/to/save/json
|
||||
```
|
||||
|
||||
To generate Markdown documentation and specify a custom output path:
|
||||
|
||||
```bash
|
||||
python generate_docs_md.py /path/to/save/markdown
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Make sure to have all necessary permissions to run these scripts and write to the specified directories.
|
||||
- Make sure to have all necessary permissions to run these scripts and write
|
||||
to the specified directories.
|
||||
- The output directories will be created if they do not exist.
|
||||
|
||||
|
||||
@ -1,266 +0,0 @@
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_json
|
||||
|
||||
# Configuration files
|
||||
editors = [
|
||||
"word",
|
||||
"cell",
|
||||
"slide",
|
||||
"forms"
|
||||
]
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def write_markdown_file(file_path, content):
|
||||
with open(file_path, 'w', encoding='utf-8') as md_file:
|
||||
md_file.write(content)
|
||||
|
||||
def remove_js_comments(text):
|
||||
# Remove single-line comments, leaving text after //
|
||||
text = re.sub(r'^\s*//\s?', '', text, flags=re.MULTILINE)
|
||||
# Remove multi-line comments, leaving text after /*
|
||||
text = re.sub(r'/\*\s*|\s*\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
def correct_description(string):
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
|
||||
# Replace opening <b> tag with **
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
# Replace closing </b> tag with **
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
# Note
|
||||
return re.sub(r'<note>(.*?)</note>', r'💡 \1', string, flags=re.DOTALL)
|
||||
|
||||
def correct_default_value(value, enumerations, classes):
|
||||
if value is None:
|
||||
return ''
|
||||
|
||||
if value == True:
|
||||
value = "true"
|
||||
elif value == False:
|
||||
value = "false"
|
||||
else:
|
||||
value = str(value)
|
||||
|
||||
return generate_data_types_markdown([value], enumerations, classes)
|
||||
|
||||
def remove_line_breaks(string):
|
||||
return re.sub(r'[\r\n]', '', string)
|
||||
|
||||
def generate_data_types_markdown(types, enumerations, classes, root='../../'):
|
||||
param_types_md = ' |'.join(types)
|
||||
|
||||
for enum in enumerations:
|
||||
if enum['name'] in types:
|
||||
param_types_md = param_types_md.replace(enum['name'], f"[{enum['name']}]({root}Enumeration/{enum['name']}.md)")
|
||||
for cls in classes:
|
||||
if cls in types:
|
||||
param_types_md = param_types_md.replace(cls, f"[{cls}]({root}{cls}/{cls}.md)")
|
||||
|
||||
def replace_with_links(match):
|
||||
element = match.group(1).strip()
|
||||
base_type = element.split('.')[0] # Take only the first part before the dot, if any
|
||||
if any(enum['name'] == base_type for enum in enumerations):
|
||||
return f"<[{element}](../../Enumeration/{base_type}.md)>"
|
||||
elif base_type in classes:
|
||||
return f"<[{element}](../../{base_type}/{base_type}.md)>"
|
||||
return f"<{element}>"
|
||||
|
||||
return re.sub(r'<([^<>]+)>', replace_with_links, param_types_md)
|
||||
|
||||
def generate_class_markdown(class_name, methods, properties, enumerations, classes):
|
||||
content = f"# {class_name}\n\nRepresents the {class_name} class.\n\n"
|
||||
|
||||
content += generate_properties_markdown(properties, enumerations, classes, '../')
|
||||
|
||||
content += "## Methods\n\n"
|
||||
for method in methods:
|
||||
method_name = method['name']
|
||||
content += f"- [{method_name}](./Methods/{method_name}.md)\n"
|
||||
return content
|
||||
|
||||
def generate_method_markdown(method, enumerations, classes):
|
||||
method_name = method['name']
|
||||
description = method.get('description', 'No description provided.')
|
||||
description = correct_description(description)
|
||||
params = method.get('params', [])
|
||||
returns = method.get('returns', [])
|
||||
example = method.get('example', '')
|
||||
memberof = method.get('memberof', '')
|
||||
|
||||
content = f"# {method_name}\n\n{description}\n\n"
|
||||
|
||||
# Syntax section
|
||||
param_list = ', '.join([param['name'] for param in params]) if params else ''
|
||||
content += f"## Syntax\n\nexpression.{method_name}({param_list});\n\n"
|
||||
if memberof:
|
||||
content += f"`expression` - A variable that represents a [{memberof}](../{memberof}.md) class.\n\n"
|
||||
|
||||
content += "## Parameters\n\n"
|
||||
|
||||
if params:
|
||||
content += "| **Name** | **Required/Optional** | **Data type** | **Default** | **Description** |\n"
|
||||
content += "| ------------- | ------------- | ------------- | ------------- | ------------- |\n"
|
||||
for param in params:
|
||||
param_name = param.get('name', 'Unnamed')
|
||||
param_types = param.get('type', {}).get('names', []) if param.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(param_types, enumerations, classes)
|
||||
param_desc = remove_line_breaks(correct_description(param.get('description', 'No description provided.')))
|
||||
param_required = "Required" if not param.get('optional') else "Optional"
|
||||
param_default = correct_default_value(param.get('defaultvalue', ''), enumerations, classes)
|
||||
|
||||
content += f"| {param_name} | {param_required} | {param_types_md} | {param_default} | {param_desc} |\n"
|
||||
else:
|
||||
content += "This method doesn't have any parameters.\n"
|
||||
|
||||
content += "\n## Returns\n\n"
|
||||
if returns:
|
||||
return_type = ', '.join(returns[0].get('type', {}).get('names', [])) if returns[0].get('type') else 'Unknown'
|
||||
|
||||
# Check for enumerations and classes in return type and add links if they exist
|
||||
return_type_md = generate_data_types_markdown([return_type], enumerations, classes)
|
||||
content += return_type_md
|
||||
else:
|
||||
content += "This method doesn't return any data."
|
||||
|
||||
if example:
|
||||
# Separate comment and code, and remove comment symbols
|
||||
comment, code = example.split('```js', 1)
|
||||
comment = remove_js_comments(comment)
|
||||
content += f"\n\n## Example\n\n{comment}\n\n```javascript\n{code.strip()}\n"
|
||||
|
||||
return content
|
||||
|
||||
def generate_properties_markdown(properties, enumerations, classes, root='../../'):
|
||||
if (properties is None):
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
for prop in properties:
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description))
|
||||
param_types_md = generate_data_types_markdown(prop['type']['names'], enumerations, classes, root)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
content += "\n"
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
enum_name = enumeration['name']
|
||||
description = enumeration.get('description', 'No description provided.')
|
||||
description = correct_description(description)
|
||||
example = enumeration.get('example', '')
|
||||
|
||||
content = f"# {enum_name}\n\n{description}\n\n"
|
||||
|
||||
if 'TypeUnion' == enumeration['type']['parsedType']['type']:
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
elements = enumeration['type']['parsedType']['elements']
|
||||
for element in elements:
|
||||
element_name = element['name'] if element['type'] != 'NullLiteral' else 'null'
|
||||
# Check if element is in enumerations or classes before adding link
|
||||
if any(enum['name'] == element_name for enum in enumerations):
|
||||
content += f"- [{element_name}](../../Enumeration/{element_name}.md)\n"
|
||||
elif element_name in classes:
|
||||
content += f"- [{element_name}](../../{element_name}/{element_name}.md)\n"
|
||||
else:
|
||||
content += f"- {element_name}\n"
|
||||
elif enumeration['properties'] is not None:
|
||||
content += "## Type\n\nObject\n\n"
|
||||
content += generate_properties_markdown(enumeration['properties'], enumerations, classes)
|
||||
else:
|
||||
content += "## Type\n\n"
|
||||
types = enumeration['type']['names']
|
||||
for t in types:
|
||||
t = generate_data_types_markdown([t], enumerations, classes)
|
||||
content += t + "\n\n"
|
||||
|
||||
if example:
|
||||
# Separate comment and code, and remove comment symbols
|
||||
comment, code = example.split('```js', 1)
|
||||
comment = remove_js_comments(comment)
|
||||
content += f"\n\n## Example\n\n{comment}\n\n```javascript\n{code.strip()}\n"
|
||||
|
||||
return content
|
||||
|
||||
def process_doclets(data, output_dir):
|
||||
classes = {}
|
||||
classes_props = {}
|
||||
enumerations = []
|
||||
|
||||
for doclet in data:
|
||||
if doclet['kind'] == 'class':
|
||||
class_name = doclet['name']
|
||||
classes[class_name] = []
|
||||
classes_props[class_name] = doclet.get('properties', None)
|
||||
elif doclet['kind'] == 'function':
|
||||
class_name = doclet.get('memberof')
|
||||
if class_name:
|
||||
if class_name not in classes:
|
||||
classes[class_name] = []
|
||||
classes[class_name].append(doclet)
|
||||
elif doclet['kind'] == 'typedef':
|
||||
enumerations.append(doclet)
|
||||
|
||||
# Process classes
|
||||
for class_name, methods in classes.items():
|
||||
class_dir = os.path.join(output_dir, class_name)
|
||||
methods_dir = os.path.join(class_dir, 'Methods')
|
||||
os.makedirs(methods_dir, exist_ok=True)
|
||||
|
||||
# Write class file
|
||||
class_content = generate_class_markdown(class_name, methods, classes_props[class_name], enumerations, classes)
|
||||
write_markdown_file(os.path.join(class_dir, f"{class_name}.md"), class_content)
|
||||
|
||||
# Write method files
|
||||
for method in methods:
|
||||
method_content = generate_method_markdown(method, enumerations, classes)
|
||||
write_markdown_file(os.path.join(methods_dir, f"{method['name']}.md"), method_content)
|
||||
|
||||
# Process enumerations
|
||||
enum_dir = os.path.join(output_dir, 'Enumeration')
|
||||
os.makedirs(enum_dir, exist_ok=True)
|
||||
|
||||
for enum in enumerations:
|
||||
enum_content = generate_enumeration_markdown(enum, enumerations, classes)
|
||||
write_markdown_file(os.path.join(enum_dir, f"{enum['name']}.md"), enum_content)
|
||||
|
||||
def generate(output_dir):
|
||||
print('Generating Markdown documentation...')
|
||||
|
||||
generate_docs_json.generate(output_dir + 'tmp_json')
|
||||
for editor_name in editors:
|
||||
input_file = os.path.join(output_dir + 'tmp_json', editor_name + ".json")
|
||||
os.makedirs(output_dir + f'/{editor_name.title()}', exist_ok=True)
|
||||
|
||||
data = load_json(input_file)
|
||||
process_doclets(data, output_dir + f'/{editor_name}')
|
||||
|
||||
shutil.rmtree(output_dir + 'tmp_json')
|
||||
print('Done')
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default="../../../../office-js-api/" # Default value
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
generate(args.destination)
|
||||
39
scripts/sdkjs_common/jsdoc/get_latest_branch.py
Normal file
39
scripts/sdkjs_common/jsdoc/get_latest_branch.py
Normal file
@ -0,0 +1,39 @@
|
||||
import subprocess
|
||||
|
||||
def fetch_branches():
|
||||
#Fetch all branches without tags from the remote.
|
||||
subprocess.run(['git', 'fetch', '--no-tags', 'origin', '+refs/heads/*:refs/remotes/origin/*'], check=True)
|
||||
|
||||
def get_branches():
|
||||
#Get list of branches in the repository."""
|
||||
result = subprocess.run(['git', 'branch', '-r'], capture_output=True, text=True)
|
||||
return [line.strip() for line in result.stdout.splitlines()]
|
||||
|
||||
def parse_version(version_str):
|
||||
#Parse version string and return a tuple of integers (major, minor, patch).
|
||||
try:
|
||||
return tuple(map(int, version_str.lstrip('v').split('.')))
|
||||
except ValueError:
|
||||
return (0, 0, 0) # Default for non-parsable versions
|
||||
|
||||
def get_max_version_branch(branches):
|
||||
#Find the branch with the highest version.
|
||||
max_branch = None
|
||||
max_version = (0, 0, 0)
|
||||
|
||||
for branch in branches:
|
||||
parts = branch.split('/')
|
||||
if len(parts) >= 2 and (parts[1] == 'hotfix' or parts[1] == 'release'):
|
||||
version = parse_version(parts[2])
|
||||
if version > max_version:
|
||||
max_version = version
|
||||
max_branch = parts
|
||||
|
||||
return max_branch
|
||||
|
||||
if __name__ == "__main__":
|
||||
fetch_branches() # Fetch branches without tags
|
||||
branches = get_branches()
|
||||
max_version_branch = get_max_version_branch(branches)
|
||||
if max_version_branch:
|
||||
print('/'.join(max_version_branch[1:])) # Print only the branch name without origin
|
||||
16
scripts/sdkjs_common/jsdoc/office-api/config/cell.json
Normal file
16
scripts/sdkjs_common/jsdoc/office-api/config/cell.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs/slide/apiBuilder.js", "../../../../../sdkjs/cell/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,11 @@ exports.handlers = {
|
||||
doclet.longname = cleanName(doclet.longname);
|
||||
doclet.name = cleanName(doclet.name);
|
||||
|
||||
// skip inherited methods if ovveriden in child class
|
||||
if (doclet.inherited && filteredDoclets.find((addedDoclet) => addedDoclet['name'] == doclet['name'] && addedDoclet['memberof'] == doclet['memberof'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const filteredDoclet = {
|
||||
comment: doclet.comment,
|
||||
description: doclet.description,
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../sdkjs/word/apiBuilder.js", "../../../../sdkjs/slide/apiBuilder.js", "../../../../sdkjs/cell/apiBuilder.js"]
|
||||
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs-forms/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
@ -13,4 +13,4 @@
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../sdkjs/word/apiBuilder.js"]
|
||||
"include": ["../../../../../sdkjs/pdf/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../sdkjs/word/apiBuilder.js", "../../../../sdkjs/slide/apiBuilder.js"]
|
||||
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs/slide/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../sdkjs/word/apiBuilder.js", "../../../../sdkjs-forms/apiBuilder.js"]
|
||||
"include": ["../../../../../sdkjs/word/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
@ -3,6 +3,10 @@ import subprocess
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
import platform
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
# Configuration files
|
||||
configs = [
|
||||
@ -19,21 +23,20 @@ editors_maps = {
|
||||
"forms": "CFE"
|
||||
}
|
||||
|
||||
def generate(output_dir):
|
||||
missing_examples_file = f'{output_dir}/missing_examples.txt'
|
||||
def generate(output_dir, md=False):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Recreate missing_examples.txt file
|
||||
with open(missing_examples_file, 'w', encoding='utf-8') as f:
|
||||
f.write('')
|
||||
|
||||
# Generate JSON documentation
|
||||
for config in configs:
|
||||
editor_name = config.split('/')[-1].replace('.json', '')
|
||||
output_file = os.path.join(output_dir, editor_name + ".json")
|
||||
command = f"set EDITOR={editors_maps[editor_name]} && npx jsdoc -c {config} -X > {output_file}"
|
||||
command_set_env = "export"
|
||||
if (platform.system().lower() == "windows"):
|
||||
command_set_env = "set"
|
||||
command = f"{command_set_env} EDITOR={editors_maps[editor_name]} && npx jsdoc -c {config} -X > {output_file}"
|
||||
print(f"Generating {editor_name}.json: {command}")
|
||||
subprocess.run(command, shell=True)
|
||||
|
||||
@ -51,9 +54,12 @@ def generate(output_dir):
|
||||
if 'see' in doclet:
|
||||
if doclet['see'] is not None:
|
||||
if editor_name == 'forms':
|
||||
file_path = '../../../../' + doclet['see'][0].replace('{Editor}', 'Word')
|
||||
doclet['see'][0] = doclet['see'][0].replace('{Editor}', 'Word')
|
||||
else:
|
||||
file_path = '../../../../' + doclet['see'][0].replace('{Editor}', editor_name.title())
|
||||
doclet['see'][0] = doclet['see'][0].replace('{Editor}', editor_name.title())
|
||||
|
||||
file_path = f'{root}/' + doclet['see'][0]
|
||||
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as see_file:
|
||||
example_content = see_file.read()
|
||||
@ -67,18 +73,20 @@ def generate(output_dir):
|
||||
comment = ''
|
||||
code_content = example_content
|
||||
|
||||
# Format content for doclet['example']
|
||||
doclet['example'] = remove_js_comments(comment) + "```js\n" + remove_builder_lines(code_content) + "\n```"
|
||||
else:
|
||||
# Record missing examples in missing_examples.txt
|
||||
with open(missing_examples_file, 'a', encoding='utf-8') as missing_file:
|
||||
missing_file.write(f"{file_path}\n")
|
||||
if md == True:
|
||||
doclet['example'] = remove_js_comments(comment) + "```js\n" + code_content + "\n```"
|
||||
|
||||
if md == False:
|
||||
document_type = editor_name
|
||||
if "forms" == document_type:
|
||||
document_type = "pdf"
|
||||
doclet['description'] = doclet['description'] + f'\n\n## Try it\n\n ```js document-builder={{"documentType": "{document_type}"}}\n{code_content}\n```'
|
||||
|
||||
# Write the modified JSON file back
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
print("Documentation generation completed.")
|
||||
print("Documentation generation for builder completed.")
|
||||
|
||||
def remove_builder_lines(text):
|
||||
lines = text.splitlines() # Split text into lines
|
||||
@ -91,25 +99,6 @@ def remove_js_comments(text):
|
||||
# Remove multi-line comments, leaving text after /*
|
||||
text = re.sub(r'/\*\s*|\s*\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
def get_current_branch(path):
|
||||
try:
|
||||
# Navigate to the specified directory and get the current branch name
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
||||
cwd=path,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return result.stdout.strip()
|
||||
else:
|
||||
print(f"Error: {result.stderr}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Exception: {e}")
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
@ -118,12 +107,7 @@ if __name__ == "__main__":
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default="../../../../document-builder-declarations/document-builder" # Default value
|
||||
default=f"{root}/office-js-api-declarations/office-js-api"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
branch_name = get_current_branch("../../../../sdkjs")
|
||||
if branch_name:
|
||||
args.destination = f"{args.destination}/{branch_name}"
|
||||
|
||||
generate(args.destination)
|
||||
591
scripts/sdkjs_common/jsdoc/office-api/generate_docs_md.py
Normal file
591
scripts/sdkjs_common/jsdoc/office-api/generate_docs_md.py
Normal file
@ -0,0 +1,591 @@
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_json
|
||||
|
||||
# Configuration files
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
}
|
||||
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
|
||||
cur_editor_name = None
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def write_markdown_file(file_path, content):
|
||||
with open(file_path, 'w', encoding='utf-8') as md_file:
|
||||
md_file.write(content)
|
||||
|
||||
def remove_js_comments(text):
|
||||
text = re.sub(r'^\s*//.*$', '', text, flags=re.MULTILINE) # single-line
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL) # multi-line
|
||||
return text.strip()
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
Finds patterns like {@link ...} and replaces them with Markdown links.
|
||||
If the prefix 'global#' is found, a link to a typedef is generated,
|
||||
otherwise, a link to a class method is created.
|
||||
For a method, if an alias is not specified, the name is left in the format 'Class#Method'.
|
||||
"""
|
||||
reserved_links = {
|
||||
'/docbuilder/global#ShapeType': f"{'../../../../../../' if root == '' else '../../../../../' if root == '../' else root}docs/office-api/usage-api/text-document-api/Enumeration/ShapeType.md",
|
||||
'/plugin/config': 'https://api.onlyoffice.com/docs/plugin-and-macros/structure/configuration/',
|
||||
'/docbuilder/basic': 'https://api.onlyoffice.com/docs/office-api/usage-api/text-document-api/'
|
||||
}
|
||||
|
||||
def replace_link(match):
|
||||
content = match.group(1).strip() # Example: "/docbuilder/global#ShapeType shape type" or "global#ErrorValue ErrorValue"
|
||||
parts = content.split()
|
||||
ref = parts[0]
|
||||
label = parts[1] if len(parts) > 1 else None
|
||||
|
||||
if ref.startswith('/'):
|
||||
# Handle reserved links using mapping
|
||||
if ref in reserved_links:
|
||||
url = reserved_links[ref]
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
else:
|
||||
# If the link is not in the mapping, return the original construction
|
||||
return match.group(0)
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
used_enumerations.add(typedef_name)
|
||||
display_text = label if label else typedef_name
|
||||
return f"[{display_text}]({root}Enumeration/{typedef_name}.md)"
|
||||
else:
|
||||
# Handle links to class methods like ClassName#MethodName
|
||||
try:
|
||||
class_name, method_name = ref.split("#")
|
||||
except ValueError:
|
||||
return match.group(0)
|
||||
display_text = label if label else ref # Keep the full notation, e.g., "Api#CreateSlide"
|
||||
return f"[{display_text}]({root}{class_name}/Methods/{method_name}.md)"
|
||||
|
||||
return re.sub(r'{@link\s+([^}]+)}', replace_link, text)
|
||||
|
||||
def correct_description(string, root='', isInTable=False):
|
||||
"""
|
||||
Cleans or transforms specific tags in the doclet description:
|
||||
- <b> => ** (bold text)
|
||||
- <note>...</note> => 💡 ...
|
||||
- {@link ...} is replaced with a Markdown link
|
||||
- If the description is missing, returns a default value.
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
string = string.replace('\r', '\\\n')
|
||||
# Replace <b> tags with Markdown bold formatting
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
# Replace <note> tags with an icon and text
|
||||
string = re.sub(r'<note>(.*?)</note>', r'💡 \1', string, flags=re.DOTALL)
|
||||
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
|
||||
def correct_default_value(value, enumerations, classes):
|
||||
if value is None or value == '':
|
||||
return ''
|
||||
|
||||
if isinstance(value, bool):
|
||||
value = "true" if value else "false"
|
||||
else:
|
||||
value = str(value)
|
||||
|
||||
return generate_data_types_markdown([value], enumerations, classes)
|
||||
|
||||
def remove_line_breaks(string):
|
||||
return re.sub(r'[\r\n]+', ' ', string)
|
||||
|
||||
# Convert Array.<T> => T[] (including nested arrays).
|
||||
def convert_jsdoc_array_to_ts(type_str: str) -> str:
|
||||
"""
|
||||
Recursively replaces 'Array.<T>' with 'T[]',
|
||||
handling nested arrays like 'Array.<Array.<string>>' => 'string[][]'.
|
||||
"""
|
||||
pattern = re.compile(r'Array\.<([^>]+)>')
|
||||
|
||||
while True:
|
||||
match = pattern.search(type_str)
|
||||
if not match:
|
||||
break
|
||||
|
||||
inner_type = match.group(1).strip()
|
||||
# Recursively convert inner parts
|
||||
inner_type = convert_jsdoc_array_to_ts(inner_type)
|
||||
|
||||
# Replace the outer Array.<...> with ...[]
|
||||
type_str = (
|
||||
type_str[:match.start()]
|
||||
+ f"{inner_type}[]"
|
||||
+ type_str[match.end():]
|
||||
)
|
||||
|
||||
return type_str
|
||||
|
||||
def escape_text_outside_code_blocks(markdown: str) -> str:
|
||||
"""
|
||||
Splits content by fenced code blocks, escapes MDX-unsafe characters
|
||||
(<, >, {, }) only in the text outside those code blocks.
|
||||
"""
|
||||
# A regex to capture fenced code blocks with ```
|
||||
parts = re.split(r'(```.*?```)', markdown, flags=re.DOTALL)
|
||||
|
||||
# Even indices (0, 2, 4, ...) are outside code blocks,
|
||||
# odd indices (1, 3, 5, ...) are actual code blocks.
|
||||
for i in range(0, len(parts), 2):
|
||||
text = (parts[i]
|
||||
.replace('<', '<')
|
||||
.replace('>', '>')
|
||||
.replace('{', '{')
|
||||
.replace('}', '}'))
|
||||
parts[i] = escape_brackets_in_quotes(text)
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
def escape_brackets_in_quotes(text: str) -> str:
|
||||
return re.sub(
|
||||
r"(['\"])(.*?)(?<!\\)\1",
|
||||
lambda m: m.group(1)
|
||||
+ m.group(2).replace('[', r'\[').replace(']', r'\]')
|
||||
+ m.group(1),
|
||||
text
|
||||
)
|
||||
|
||||
def get_base_type(ts_type: str) -> str:
|
||||
"""
|
||||
Given a TypeScript-like type (e.g. "Drawing[][]"), return the
|
||||
'base' portion by stripping trailing "[]". For "Drawing[][]",
|
||||
returns "Drawing". For "Array.<Drawing>", you'd convert it first
|
||||
to "Drawing[]" then return "Drawing".
|
||||
"""
|
||||
while ts_type.endswith('[]'):
|
||||
ts_type = ts_type[:-2]
|
||||
return ts_type
|
||||
|
||||
def generate_data_types_markdown(types, enumerations, classes, root='../../'):
|
||||
"""
|
||||
1) Converts each type from JSDoc (e.g., Array.<T>) to T[].
|
||||
2) Processes union types by splitting them using '|'.
|
||||
3) Supports multidimensional arrays, e.g., (string|ApiRange|number)[].
|
||||
4) If the base type matches the name of an enumeration or class, generates a link.
|
||||
5) The final types are joined using " | ".
|
||||
"""
|
||||
# Convert each type from JSDoc format to TypeScript format (e.g., T[])
|
||||
converted = [convert_jsdoc_array_to_ts(t) for t in types]
|
||||
|
||||
# Set of primitive types
|
||||
primitive_types = {"string", "number", "boolean", "null", "undefined", "any", "object", "false", "true", "json", "function", "date", "{}"}
|
||||
|
||||
def is_primitive(type):
|
||||
if (type.lower() in primitive_types or
|
||||
(type.startswith('"') and type.endswith('"')) or
|
||||
(type.startswith("'") and type.endswith("'")) or
|
||||
type.replace('.', '', 1).isdigit() or
|
||||
(type.startswith('-') and type[1:].replace('.', '', 1).isdigit())):
|
||||
return True
|
||||
return False
|
||||
|
||||
def link_if_known(ts_type):
|
||||
ts_type = ts_type.strip()
|
||||
# Count the number of array dimensions, e.g., "[][]" has 2 dimensions
|
||||
array_dims = 0
|
||||
while ts_type.endswith("[]"):
|
||||
array_dims += 1
|
||||
ts_type = ts_type[:-2].strip()
|
||||
|
||||
# Process generic types, e.g., Object.<string, editorType>
|
||||
if ".<" in ts_type and ts_type.endswith(">"):
|
||||
import re
|
||||
m = re.match(r'^(.*?)\.<(.*)>$', ts_type)
|
||||
if m:
|
||||
base_part = m.group(1).strip()
|
||||
generic_args_str = m.group(2).strip()
|
||||
# Process the base part of the type
|
||||
found = False
|
||||
for enum in enumerations:
|
||||
if enum['name'] == base_part:
|
||||
used_enumerations.add(base_part)
|
||||
base_result = f"[{base_part}]({root}Enumeration/{base_part}.md)"
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if base_part in classes:
|
||||
base_result = f"[{base_part}]({root}{base_part}/{base_part}.md)"
|
||||
elif is_primitive(base_part):
|
||||
base_result = base_part
|
||||
elif cur_editor_name == "forms":
|
||||
base_result = f"[{base_part}]({root}../text-document-api/{base_part}/{base_part}.md)"
|
||||
else:
|
||||
print(f"Unknown type encountered: {base_part}")
|
||||
base_result = base_part
|
||||
# Split the generic parameters by commas and process each recursively
|
||||
generic_args = [link_if_known(x) for x in generic_args_str.split(",")]
|
||||
result = base_result + ".<" + ", ".join(generic_args) + ">"
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# Process union types: if the type is enclosed in parentheses
|
||||
if ts_type.startswith("(") and ts_type.endswith(")"):
|
||||
inner = ts_type[1:-1].strip()
|
||||
subtypes = [sub.strip() for sub in inner.split("|")]
|
||||
if len(subtypes) == 1:
|
||||
result = link_if_known(subtypes[0])
|
||||
else:
|
||||
processed = [link_if_known(subtype) for subtype in subtypes]
|
||||
result = "(" + " | ".join(processed) + ")"
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# If not a generic or union type – process the base type
|
||||
else:
|
||||
base = ts_type
|
||||
found = False
|
||||
for enum in enumerations:
|
||||
if enum['name'] == base:
|
||||
used_enumerations.add(base)
|
||||
result = f"[{base}]({root}Enumeration/{base}.md)"
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if base in classes:
|
||||
result = f"[{base}]({root}{base}/{base}.md)"
|
||||
elif is_primitive(base):
|
||||
result = base
|
||||
elif cur_editor_name == "forms":
|
||||
result = f"[{base}]({root}../text-document-api/{base}/{base}.md)"
|
||||
else:
|
||||
print(f"Unknown type encountered: {base}")
|
||||
result = base
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# Apply link_if_known to each converted type
|
||||
linked = [link_if_known(ts_t) for ts_t in converted]
|
||||
|
||||
# Join results using " | "
|
||||
param_types_md = r' | '.join(linked)
|
||||
param_types_md = param_types_md.replace("|", r"\|")
|
||||
|
||||
# Escape remaining angle brackets for generics
|
||||
def replace_leftover_generics(match):
|
||||
element = match.group(1).strip()
|
||||
return f"<{element}>"
|
||||
|
||||
param_types_md = re.sub(r'<([^<>]+)>', replace_leftover_generics, param_types_md)
|
||||
|
||||
return param_types_md
|
||||
|
||||
|
||||
def generate_class_markdown(class_name, methods, properties, enumerations, classes):
|
||||
content = f"# {class_name}\n\nRepresents the {class_name} class.\n\n"
|
||||
|
||||
content += generate_properties_markdown(properties, enumerations, classes)
|
||||
|
||||
content += "\n## Methods\n\n"
|
||||
content += "| Method | Returns | Description |\n"
|
||||
content += "| ------ | ------- | ----------- |\n"
|
||||
|
||||
for method in sorted(methods, key=lambda m: m['name']):
|
||||
method_name = method['name']
|
||||
|
||||
# Get the type of return values
|
||||
returns = method.get('returns', [])
|
||||
if returns:
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
returns_markdown = generate_data_types_markdown(return_type_list, enumerations, classes, '../')
|
||||
else:
|
||||
returns_markdown = "None"
|
||||
|
||||
# Processing the method description
|
||||
description = remove_line_breaks(correct_description(method.get('description', 'No description provided.'), '../', True))
|
||||
|
||||
# Form a link to the method document
|
||||
method_link = f"[{method_name}](./Methods/{method_name}.md)"
|
||||
|
||||
content += f"| {method_link} | {returns_markdown} | {description} |\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_method_markdown(method, enumerations, classes, example_editor_name):
|
||||
method_name = method['name']
|
||||
description = method.get('description', 'No description provided.')
|
||||
description = correct_description(description, '../../')
|
||||
params = method.get('params', [])
|
||||
returns = method.get('returns', [])
|
||||
example = method.get('example', '')
|
||||
memberof = method.get('memberof', '')
|
||||
|
||||
content = f"# {method_name}\n\n{description}\n\n"
|
||||
|
||||
# Syntax
|
||||
param_list = ', '.join([param['name'] for param in params if '.' not in param['name']]) if params else ''
|
||||
content += f"## Syntax\n\n```javascript\nexpression.{method_name}({param_list});\n```\n\n"
|
||||
if memberof:
|
||||
content += f"`expression` - A variable that represents a [{memberof}](../{memberof}.md) class.\n\n"
|
||||
|
||||
# Parameters
|
||||
content += "## Parameters\n\n"
|
||||
if params:
|
||||
content += "| **Name** | **Required/Optional** | **Data type** | **Default** | **Description** |\n"
|
||||
content += "| ------------- | ------------- | ------------- | ------------- | ------------- |\n"
|
||||
for param in params:
|
||||
param_name = param.get('name', 'Unnamed')
|
||||
param_types = param.get('type', {}).get('names', []) if param.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(param_types, enumerations, classes)
|
||||
param_desc = remove_line_breaks(correct_description(param.get('description', 'No description provided.'), '../../', True))
|
||||
param_required = "Required" if not param.get('optional') else "Optional"
|
||||
param_default = correct_default_value(param.get('defaultvalue', ''), enumerations, classes)
|
||||
|
||||
content += f"| {param_name} | {param_required} | {param_types_md} | {param_default} | {param_desc} |\n"
|
||||
else:
|
||||
content += "This method doesn't have any parameters.\n"
|
||||
|
||||
# Returns
|
||||
content += "\n## Returns\n\n"
|
||||
if returns:
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
return_type_md = generate_data_types_markdown(return_type_list, enumerations, classes)
|
||||
content += return_type_md
|
||||
else:
|
||||
content += "This method doesn't return any data."
|
||||
|
||||
# Example
|
||||
if example:
|
||||
# Separate comment and code, remove JS comments
|
||||
if '```js' in example:
|
||||
comment, code = example.split('```js', 1)
|
||||
comment = remove_js_comments(comment)
|
||||
content += f"\n\n## Example\n\n{comment}\n\n```javascript {example_editor_name}\n{code.strip()}\n"
|
||||
else:
|
||||
# If there's no triple-backtick structure, just show it as code
|
||||
cleaned_example = remove_js_comments(example)
|
||||
content += f"\n\n## Example\n\n```javascript {example_editor_name}\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_properties_markdown(properties, enumerations, classes, root='../'):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
|
||||
for prop in sorted(properties, key=lambda m: m['name']):
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description, root, True))
|
||||
prop_types = prop['type']['names'] if prop.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(prop_types, enumerations, classes, root)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
|
||||
# Escape outside code blocks
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_enumeration_markdown(enumeration, enumerations, classes, example_editor_name):
|
||||
enum_name = enumeration['name']
|
||||
|
||||
if enum_name not in used_enumerations:
|
||||
return None
|
||||
|
||||
description = enumeration.get('description', 'No description provided.')
|
||||
description = correct_description(description, '../')
|
||||
example = enumeration.get('example', '')
|
||||
|
||||
content = f"# {enum_name}\n\n{description}\n\n"
|
||||
|
||||
ptype = enumeration['type']['parsedType']
|
||||
if ptype['type'] == 'TypeUnion':
|
||||
enum_empty = True # is empty enum
|
||||
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
# Each top-level name in the union
|
||||
for raw_t in enumeration['type']['names']:
|
||||
ts_t = convert_jsdoc_array_to_ts(raw_t)
|
||||
|
||||
# Attempt linking: we compare the raw type to enumerations/classes
|
||||
if any(enum['name'] == raw_t for enum in enumerations):
|
||||
used_enumerations.add(raw_t)
|
||||
content += f"- [{ts_t}](../Enumeration/{raw_t}.md)\n"
|
||||
enum_empty = False
|
||||
elif raw_t in classes:
|
||||
content += f"- [{ts_t}](../{raw_t}/{raw_t}.md)\n"
|
||||
enum_empty = False
|
||||
elif ts_t.find('Api') == -1:
|
||||
content += f"- {ts_t}\n"
|
||||
enum_empty = False
|
||||
|
||||
if enum_empty == True:
|
||||
return None
|
||||
elif enumeration['properties'] is not None:
|
||||
content += "## Type\n\nObject\n\n"
|
||||
content += generate_properties_markdown(enumeration['properties'], enumerations, classes)
|
||||
else:
|
||||
content += "## Type\n\n"
|
||||
# If it's not a union and has no properties, simply print the type(s).
|
||||
types = enumeration['type']['names']
|
||||
t_md = generate_data_types_markdown(types, enumerations, classes)
|
||||
content += t_md + "\n\n"
|
||||
|
||||
# Example
|
||||
if example:
|
||||
if '```js' in example:
|
||||
comment, code = example.split('```js', 1)
|
||||
comment = remove_js_comments(comment)
|
||||
content += f"\n\n## Example\n\n{comment}\n\n```javascript {example_editor_name}\n{code.strip()}\n"
|
||||
else:
|
||||
# If there's no triple-backtick structure
|
||||
cleaned_example = remove_js_comments(example)
|
||||
content += f"\n\n## Example\n\n```javascript {example_editor_name}\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def process_doclets(data, output_dir, editor_name):
|
||||
global cur_editor_name
|
||||
cur_editor_name = editor_name
|
||||
|
||||
classes = {}
|
||||
classes_props = {}
|
||||
enumerations = []
|
||||
editor_dir = os.path.join(output_dir, editors[editor_name])
|
||||
example_editor_name = 'editor-'
|
||||
|
||||
if editor_name == 'word':
|
||||
example_editor_name += 'docx'
|
||||
elif editor_name == 'forms':
|
||||
example_editor_name += 'pdf'
|
||||
elif editor_name == 'slide':
|
||||
example_editor_name += 'pptx'
|
||||
elif editor_name == 'cell':
|
||||
example_editor_name += 'xlsx'
|
||||
|
||||
for doclet in data:
|
||||
if doclet['kind'] == 'class':
|
||||
class_name = doclet['name']
|
||||
if class_name:
|
||||
if class_name not in classes:
|
||||
classes[class_name] = []
|
||||
classes_props[class_name] = doclet.get('properties', None)
|
||||
elif doclet['kind'] == 'function':
|
||||
class_name = doclet.get('memberof')
|
||||
if class_name:
|
||||
if class_name not in classes:
|
||||
classes[class_name] = []
|
||||
classes[class_name].append(doclet)
|
||||
elif doclet['kind'] == 'typedef':
|
||||
enumerations.append(doclet)
|
||||
|
||||
# Process classes
|
||||
for class_name, methods in classes.items():
|
||||
if (len(methods) == 0):
|
||||
continue
|
||||
|
||||
class_dir = os.path.join(editor_dir, class_name)
|
||||
methods_dir = os.path.join(class_dir, 'Methods')
|
||||
os.makedirs(methods_dir, exist_ok=True)
|
||||
|
||||
# Write class file
|
||||
class_content = generate_class_markdown(
|
||||
class_name,
|
||||
methods,
|
||||
classes_props[class_name],
|
||||
enumerations,
|
||||
classes
|
||||
)
|
||||
write_markdown_file(os.path.join(class_dir, f"{class_name}.md"), class_content)
|
||||
|
||||
# Write method files
|
||||
for method in methods:
|
||||
method_file_path = os.path.join(methods_dir, f"{method['name']}.md")
|
||||
method_content = generate_method_markdown(method, enumerations, classes, example_editor_name)
|
||||
write_markdown_file(method_file_path, method_content)
|
||||
|
||||
if not method.get('example', ''):
|
||||
missing_examples.append(os.path.relpath(method_file_path, output_dir))
|
||||
|
||||
# Process enumerations
|
||||
enum_dir = os.path.join(editor_dir, 'Enumeration')
|
||||
os.makedirs(enum_dir, exist_ok=True)
|
||||
|
||||
# idle run
|
||||
prev_used_count = -1
|
||||
while len(used_enumerations) != prev_used_count:
|
||||
prev_used_count = len(used_enumerations)
|
||||
for enum in [e for e in enumerations if e['name'] in used_enumerations]:
|
||||
enum_content = generate_enumeration_markdown(enum, enumerations, classes, example_editor_name)
|
||||
|
||||
for enum in enumerations:
|
||||
enum_file_path = os.path.join(enum_dir, f"{enum['name']}.md")
|
||||
enum_content = generate_enumeration_markdown(enum, enumerations, classes, example_editor_name)
|
||||
if enum_content is None:
|
||||
continue
|
||||
|
||||
write_markdown_file(enum_file_path, enum_content)
|
||||
if not enum.get('example', ''):
|
||||
missing_examples.append(os.path.relpath(enum_file_path, output_dir))
|
||||
|
||||
def generate(output_dir):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
print('Generating Markdown documentation...')
|
||||
|
||||
generate_docs_json.generate(output_dir + 'tmp_json', md=True)
|
||||
for editor_name, folder_name in editors.items():
|
||||
input_file = os.path.join(output_dir + '/tmp_json', editor_name + ".json")
|
||||
|
||||
editor_folder_path = os.path.join(output_dir, folder_name)
|
||||
for folder_name in os.listdir(editor_folder_path):
|
||||
folder_path_to_del = os.path.join(editor_folder_path, folder_name)
|
||||
if os.path.isdir(folder_path_to_del):
|
||||
shutil.rmtree(folder_path_to_del, ignore_errors=True)
|
||||
|
||||
data = load_json(input_file)
|
||||
used_enumerations.clear()
|
||||
process_doclets(data, output_dir, editor_name)
|
||||
|
||||
shutil.rmtree(output_dir + 'tmp_json')
|
||||
print('Done')
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/office-api/usage-api/" # Default value
|
||||
)
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
print("START_MISSING_EXAMPLES")
|
||||
print(",".join(missing_examples))
|
||||
print("END_MISSING_EXAMPLES")
|
||||
249
scripts/sdkjs_common/jsdoc/office-api/generate_jsonl_dataset.py
Normal file
249
scripts/sdkjs_common/jsdoc/office-api/generate_jsonl_dataset.py
Normal file
@ -0,0 +1,249 @@
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_json
|
||||
from datetime import datetime
|
||||
|
||||
# Configuration files
|
||||
editors = [
|
||||
"word",
|
||||
"cell",
|
||||
"slide",
|
||||
"forms"
|
||||
]
|
||||
|
||||
editors_names = {
|
||||
"word": "Word",
|
||||
"cell": "Spreadsheet",
|
||||
"slide": "Presentation",
|
||||
"forms": "Forms"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
missing_examples = []
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def read_file_content(file_path):
|
||||
try:
|
||||
with open(file_path, encoding='utf-8') as f:
|
||||
return f.read()
|
||||
except Exception as e:
|
||||
missing_examples.append(file_path)
|
||||
# print(f"Failed to open file {file_path}: {e}")
|
||||
return ""
|
||||
|
||||
def extract_js_comments_as_text(text):
|
||||
# Extract single-line comments (after //)
|
||||
single_line_comments = re.findall(r'^\s*//(.*)$', text, flags=re.MULTILINE)
|
||||
# Extract multi-line comments (between /* and */)
|
||||
multi_line_comments = re.findall(r'/\*(.*?)\*/', text, flags=re.DOTALL)
|
||||
# Combine all found comments into a single list
|
||||
all_comments = single_line_comments + multi_line_comments
|
||||
# Join comments into a single text, separated by a space
|
||||
return " ".join(comment.strip() for comment in all_comments if comment.strip())
|
||||
|
||||
def extract_examples_blocks(content: str):
|
||||
blocks = []
|
||||
current_block = {"comments": [], "code": []}
|
||||
in_comment_section = True # Collect comments until code appears
|
||||
current_comment_group = [] # Accumulate lines of the current comment
|
||||
|
||||
for line in content.splitlines():
|
||||
stripped = line.strip()
|
||||
if not stripped:
|
||||
# Empty line
|
||||
if in_comment_section and current_comment_group:
|
||||
# Finish the current comment group
|
||||
comment_text = " ".join(current_comment_group)
|
||||
current_block["comments"].append(comment_text)
|
||||
current_comment_group = []
|
||||
elif not in_comment_section:
|
||||
# Empty line in the code – keep it as is
|
||||
current_block["code"].append(line)
|
||||
continue
|
||||
|
||||
if stripped.startswith("//"):
|
||||
if in_comment_section:
|
||||
# Remove comment marker and extra spaces
|
||||
current_comment_group.append(extract_js_comments_as_text(stripped))
|
||||
else:
|
||||
# Comment after code starts – finish the current block and start a new one
|
||||
blocks.append({
|
||||
"comments": current_block["comments"],
|
||||
"code": "\n".join(current_block["code"]).rstrip()
|
||||
})
|
||||
current_block = {"comments": [], "code": []}
|
||||
in_comment_section = True
|
||||
# Start a new comment group with the current line
|
||||
current_comment_group = [stripped[2:].strip()]
|
||||
else:
|
||||
# Code line
|
||||
if in_comment_section:
|
||||
if current_comment_group:
|
||||
comment_text = " ".join(current_comment_group)
|
||||
current_block["comments"].append(comment_text)
|
||||
current_comment_group = []
|
||||
in_comment_section = False
|
||||
current_block["code"].append(line)
|
||||
|
||||
# Finalize any remaining comment group
|
||||
if in_comment_section and current_comment_group:
|
||||
comment_text = " ".join(current_comment_group)
|
||||
current_block["comments"].append(comment_text)
|
||||
# Save the last block if it's not empty
|
||||
if current_block["comments"] or current_block["code"]:
|
||||
blocks.append({
|
||||
"comments": current_block["comments"],
|
||||
"code": "\n".join(current_block["code"]).rstrip()
|
||||
})
|
||||
|
||||
return blocks
|
||||
|
||||
def extract_examples_blocks_temp(content: str):
|
||||
lines = content.splitlines()
|
||||
comment_blocks = []
|
||||
current_group = []
|
||||
first_code_index = None
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
stripped = line.strip()
|
||||
if not stripped:
|
||||
if current_group:
|
||||
comment_blocks.append(" ".join(current_group))
|
||||
current_group = []
|
||||
continue
|
||||
if stripped.startswith("//"):
|
||||
current_group.append(stripped[2:].strip())
|
||||
else:
|
||||
if current_group:
|
||||
comment_blocks.append(" ".join(current_group))
|
||||
current_group = []
|
||||
first_code_index = i
|
||||
break
|
||||
|
||||
code_part = ""
|
||||
if first_code_index is not None:
|
||||
code_part = "\n".join(lines[first_code_index:]).rstrip()
|
||||
|
||||
return [{"comments": comment_blocks, "code": code_part}]
|
||||
|
||||
def create_entry(system_message, user_message, assistant_message, model):
|
||||
entry = {
|
||||
"created_at": datetime.now().isoformat(" "),
|
||||
"messages": [
|
||||
{"role": "system", "content": system_message},
|
||||
{"role": "user", "content": user_message},
|
||||
{"role": "assistant", "content": assistant_message}
|
||||
],
|
||||
"recommended": False,
|
||||
"upvoted": True
|
||||
}
|
||||
|
||||
if model is not "":
|
||||
entry["model"] = model
|
||||
|
||||
return entry
|
||||
|
||||
def process_doclets(doclets, output_entries, editor_name, model):
|
||||
system_message = f'You are an expert in API for library from OnlyOffice. The library provides functions for editing {editors_names[editor_name]} documents. Your functional capabilities: 1) Explanation of Onlyoffice JavaScript API classes and their methods and parameters. 2) Assistance in writing Onlyoffice JavaScript API examples upon user request. 3) Reviewing user examples, assisting in finding and fixing their mistakes.'
|
||||
|
||||
for doclet in doclets:
|
||||
kind = doclet.get("kind", "").lower()
|
||||
see = doclet.get("see", [])
|
||||
|
||||
# The "see" field must always be present
|
||||
if not see:
|
||||
continue
|
||||
|
||||
# Processing based on the "kind" value
|
||||
if kind == "function":
|
||||
method_name = doclet.get("name", "")
|
||||
memberof = doclet.get("memberof", "")
|
||||
# Functions must have both "name" (method_name) and "memberof" fields filled
|
||||
if not (method_name and memberof):
|
||||
continue
|
||||
default_user_message = f"How do I use the method {method_name} of {memberof} class?"
|
||||
|
||||
elif kind == "class":
|
||||
class_name = doclet.get("name", "")
|
||||
default_user_message = f"How do I instantiate or work with the class {class_name}?"
|
||||
|
||||
elif kind == "typedef":
|
||||
typedef_name = doclet.get("name", "")
|
||||
default_user_message = f"How do I use the typedef {typedef_name}?"
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
# Read the content of the first file listed in the "see" field
|
||||
content = read_file_content(f'{root}/{see[0]}')
|
||||
if content == "":
|
||||
continue
|
||||
|
||||
# now use only first block cause there is bad comments in examples
|
||||
blocks = extract_examples_blocks_temp(content)
|
||||
|
||||
for block in blocks:
|
||||
assistant_message = block['code']
|
||||
|
||||
# default entry
|
||||
output_entries.append(create_entry(system_message, default_user_message, assistant_message, model))
|
||||
|
||||
# If the file content contains comments, create a separate entry for each one
|
||||
for comment in block['comments']:
|
||||
output_entries.append(create_entry(system_message, comment, assistant_message, model))
|
||||
|
||||
def generate(output_dir, model):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
print('Generating documentation JSONL dataset...')
|
||||
|
||||
shutil.rmtree(output_dir, ignore_errors=True)
|
||||
os.makedirs(output_dir)
|
||||
|
||||
generate_docs_json.generate(f'{output_dir}/tmp_json')
|
||||
|
||||
output_entries = []
|
||||
output_filename = "dataset.jsonl"
|
||||
|
||||
for editor_name in editors:
|
||||
input_file = os.path.join(f'{output_dir}/tmp_json', editor_name + ".json")
|
||||
doclets = load_json(input_file)
|
||||
process_doclets(doclets, output_entries, editor_name, model)
|
||||
|
||||
with open(f'{output_dir}/{output_filename}', "w", encoding="utf-8") as out_file:
|
||||
for entry in output_entries:
|
||||
out_file.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
||||
|
||||
shutil.rmtree(f'{output_dir}/tmp_json')
|
||||
print('Done')
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation JSONL dataset")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/office-js-api/dataset" # Default value
|
||||
)
|
||||
parser.add_argument(
|
||||
"model",
|
||||
type=str,
|
||||
help="Type of model",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default="" # Default value
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
generate(args.destination, args.model)
|
||||
print("START_MISSING_EXAMPLES")
|
||||
print(",".join(missing_examples))
|
||||
print("END_MISSING_EXAMPLES")
|
||||
85
scripts/sdkjs_common/jsdoc/plugins/config/correct_doclets.js
Normal file
85
scripts/sdkjs_common/jsdoc/plugins/config/correct_doclets.js
Normal file
@ -0,0 +1,85 @@
|
||||
exports.handlers = {
|
||||
processingComplete: function(e) {
|
||||
const filteredDoclets = [];
|
||||
|
||||
function checkNullProps(oDoclet) {
|
||||
for (let key of Object.keys(oDoclet)) {
|
||||
if (oDoclet[key] == null) {
|
||||
delete oDoclet[key];
|
||||
}
|
||||
if (typeof(oDoclet[key]) == "object") {
|
||||
checkNullProps(oDoclet[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < e.doclets.length; i++) {
|
||||
const doclet = e.doclets[i];
|
||||
if (true == doclet.undocumented || doclet.kind == 'package') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const filteredDoclet = {
|
||||
comment: doclet.comment,
|
||||
|
||||
meta: doclet.meta ? {
|
||||
lineno: doclet.meta.lineno,
|
||||
columnno: doclet.meta.columnno
|
||||
} : doclet.meta,
|
||||
|
||||
kind: doclet.kind,
|
||||
since: doclet.since,
|
||||
name: doclet.name,
|
||||
type: doclet.type ? {
|
||||
names: doclet.type.names,
|
||||
parsedType: doclet.type.parsedType
|
||||
} : doclet.type,
|
||||
|
||||
description: doclet.description,
|
||||
memberof: doclet.memberof,
|
||||
|
||||
properties: doclet.properties ? doclet.properties.map(property => ({
|
||||
type: property.type ? {
|
||||
names: property.type.names,
|
||||
parsedType: property.type.parsedType
|
||||
} : property.type,
|
||||
|
||||
name: property.name,
|
||||
description: property.description,
|
||||
optional: property.optional,
|
||||
defaultvalue: property.defaultvalue
|
||||
})) : doclet.properties,
|
||||
|
||||
longname: doclet.longname,
|
||||
scope: doclet.scope,
|
||||
alias: doclet.alias,
|
||||
|
||||
params: doclet.params ? doclet.params.map(param => ({
|
||||
type: param.type ? {
|
||||
names: param.type.names,
|
||||
parsedType: param.type.parsedType
|
||||
} : param.type,
|
||||
|
||||
name: param.name,
|
||||
description: param.description,
|
||||
optional: param.optional,
|
||||
defaultvalue: param.defaultvalue
|
||||
})) : doclet.params,
|
||||
|
||||
returns: doclet.returns ? doclet.returns.map(returnObj => ({
|
||||
type: {
|
||||
names: returnObj.type.names,
|
||||
parsedType: returnObj.type.parsedType
|
||||
}
|
||||
})) : doclet.returns,
|
||||
see: doclet.see
|
||||
};
|
||||
|
||||
checkNullProps(filteredDoclet)
|
||||
|
||||
filteredDoclets.push(filteredDoclet);
|
||||
}
|
||||
|
||||
e.doclets.splice(0, e.doclets.length, ...filteredDoclets);
|
||||
}
|
||||
};
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/cell.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/cell.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/cell/plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/common.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/common.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/common/base-plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/forms.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/forms.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs-forms/plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/slide.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/slide.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/slide/plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/word.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/word.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/word/plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/cell.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/cell.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/cell/api_plugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/common/plugins/plugin_base_api.js" ,"../../../../../sdkjs/common/apiBase_plugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/forms.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/forms.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs-forms/apiPlugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/slide.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/slide.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/slide/api_plugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/word.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/word.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/word/api_plugins.js", "../../../../../sdkjs-forms/apiPlugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
114
scripts/sdkjs_common/jsdoc/plugins/generate_docs_events_json.py
Normal file
114
scripts/sdkjs_common/jsdoc/plugins/generate_docs_events_json.py
Normal file
@ -0,0 +1,114 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
|
||||
# Configuration files
|
||||
configs = [
|
||||
"./config/events/common.json",
|
||||
"./config/events/word.json",
|
||||
"./config/events/cell.json",
|
||||
"./config/events/slide.json",
|
||||
"./config/events/forms.json"
|
||||
]
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
def generate(output_dir, md=False):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Generate JSON documentation
|
||||
for config in configs:
|
||||
editor_name = config.split('/')[-1].replace('.json', '')
|
||||
output_file = os.path.join(output_dir, editor_name + ".json")
|
||||
command = f"npx jsdoc -c {config} -X > {output_file}"
|
||||
print(f"Generating {editor_name}.json: {command}")
|
||||
subprocess.run(command, shell=True)
|
||||
|
||||
common_doclets_file = os.path.join(output_dir, 'common.json')
|
||||
with open(common_doclets_file, 'r', encoding='utf-8') as f:
|
||||
common_doclets_json = json.dumps(json.load(f))
|
||||
os.remove(common_doclets_file)
|
||||
|
||||
# Append examples to JSON documentation
|
||||
for config in configs:
|
||||
if (config.find('common') != -1):
|
||||
continue
|
||||
|
||||
editor_name = config.split('/')[-1].replace('.json', '')
|
||||
example_folder_name = editor_name # name of folder with examples
|
||||
output_file = os.path.join(output_dir, editor_name + ".json")
|
||||
|
||||
# Read the JSON file
|
||||
with open(output_file, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
start_common_doclet_idx = len(data)
|
||||
data += json.loads(common_doclets_json)
|
||||
|
||||
# Modify JSON data
|
||||
for idx, doclet in enumerate(data):
|
||||
if idx >= start_common_doclet_idx:
|
||||
example_folder_name = 'common'
|
||||
elif editor_name == 'forms':
|
||||
example_folder_name = 'word'
|
||||
|
||||
if 'see' in doclet:
|
||||
if doclet['see'] is not None:
|
||||
doclet['see'][0] = doclet['see'][0].replace('{Editor}', example_folder_name.title())
|
||||
file_path = f'{root}/' + doclet['see'][0]
|
||||
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as see_file:
|
||||
example_content = see_file.read()
|
||||
|
||||
# Extract the first line as a comment if it exists
|
||||
lines = example_content.split('\n')
|
||||
if lines[0].startswith('//'):
|
||||
comment = lines[0] + '\n'
|
||||
code_content = '\n'.join(lines[1:])
|
||||
else:
|
||||
comment = ''
|
||||
code_content = example_content
|
||||
|
||||
doclet['examples'] = [remove_js_comments(comment) + code_content]
|
||||
|
||||
if md == False:
|
||||
document_type = editor_name
|
||||
if "forms" == document_type:
|
||||
document_type = "pdf"
|
||||
doclet['description'] = doclet['description'] + f'\n\n## Try it\n\n ```js document-builder={{"documentType": "{document_type}"}}\n{code_content}\n```'
|
||||
|
||||
# Write the modified JSON file back
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
print("Documentation generation for plugin events completed.")
|
||||
|
||||
def remove_builder_lines(text):
|
||||
lines = text.splitlines() # Split text into lines
|
||||
filtered_lines = [line for line in lines if not line.strip().startswith("builder.")]
|
||||
return "\n".join(filtered_lines)
|
||||
|
||||
def remove_js_comments(text):
|
||||
# Remove single-line comments, leaving text after //
|
||||
text = re.sub(r'^\s*//\s?', '', text, flags=re.MULTILINE)
|
||||
# Remove multi-line comments, leaving text after /*
|
||||
text = re.sub(r'/\*\s*|\s*\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/office-js-api-declarations/office-js-api-plugins"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
403
scripts/sdkjs_common/jsdoc/plugins/generate_docs_events_md.py
Normal file
403
scripts/sdkjs_common/jsdoc/plugins/generate_docs_events_md.py
Normal file
@ -0,0 +1,403 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_events_json
|
||||
|
||||
# Папки для каждого editor_name
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
|
||||
|
||||
def load_json(path):
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def write_markdown_file(path, content):
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
def remove_js_comments(text):
|
||||
text = re.sub(r'^\s*//.*$', '', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
|
||||
def correct_description(string, root='', isInTable=False):
|
||||
"""
|
||||
Cleans or transforms specific tags in the doclet description:
|
||||
- <b> => ** (bold text)
|
||||
- <note>...</note> => 💡 ...
|
||||
- {@link ...} is replaced with a Markdown link
|
||||
- If the description is missing, returns a default value.
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
string = string.replace('\r', '\\\n')
|
||||
# Replace <b> tags with Markdown bold formatting
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
# Replace <note> tags with an icon and text
|
||||
string = re.sub(r'<note>(.*?)</note>', r'💡 \1', string, flags=re.DOTALL)
|
||||
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
Finds patterns like {@link ...} and replaces them with Markdown links.
|
||||
If the prefix 'global#' is found, a link to a typedef is generated,
|
||||
otherwise, a link to a class method is created.
|
||||
For a method, if an alias is not specified, the name is left in the format 'Class#Method'.
|
||||
"""
|
||||
reserved_links = {
|
||||
'/docbuilder/global#ShapeType': f"{'../../../../../../' if root == '' else '../../../../../' if root == '../' else root}docs/office-api/usage-api/text-document-api/Enumeration/ShapeType.md",
|
||||
'/plugin/config': 'https://api.onlyoffice.com/docs/plugin-and-macros/structure/configuration/',
|
||||
'/docbuilder/basic': 'https://api.onlyoffice.com/docs/office-api/usage-api/text-document-api/'
|
||||
}
|
||||
|
||||
def replace_link(match):
|
||||
content = match.group(1).strip() # Example: "/docbuilder/global#ShapeType shape type" or "global#ErrorValue ErrorValue"
|
||||
parts = content.split()
|
||||
ref = parts[0]
|
||||
label = parts[1] if len(parts) > 1 else None
|
||||
|
||||
if ref.startswith('/'):
|
||||
# Handle reserved links using mapping
|
||||
if ref in reserved_links:
|
||||
url = reserved_links[ref]
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
elif ref.startswith('/docs/plugins/'):
|
||||
url = f"../../{ref.split('/docs/plugins/')[1]}.md"
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
else:
|
||||
# If the link is not in the mapping, return the original construction
|
||||
return match.group(0)
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
used_enumerations.add(typedef_name)
|
||||
display_text = label if label else typedef_name
|
||||
return f"[{display_text}]({root}Enumeration/Event_{typedef_name}.md)"
|
||||
else:
|
||||
# Handle links to class methods like ClassName#MethodName
|
||||
try:
|
||||
class_name, method_name = ref.split("#")
|
||||
except ValueError:
|
||||
return match.group(0)
|
||||
display_text = label if label else ref # Keep the full notation, e.g., "Api#CreateSlide"
|
||||
return f"[{display_text}]({root}{class_name}/Methods/{method_name}.md)"
|
||||
|
||||
return re.sub(r'{@link\s+([^}]+)}', replace_link, text)
|
||||
|
||||
def remove_line_breaks(s):
|
||||
return re.sub(r'[\r\n]+', ' ', s)
|
||||
|
||||
|
||||
def convert_jsdoc_array_to_ts(type_str):
|
||||
p = re.compile(r'Array\.<([^>]+)>')
|
||||
while True:
|
||||
m = p.search(type_str)
|
||||
if not m:
|
||||
break
|
||||
inner = convert_jsdoc_array_to_ts(m.group(1).strip())
|
||||
type_str = type_str[:m.start()] + inner + '[]' + type_str[m.end():]
|
||||
return type_str
|
||||
|
||||
|
||||
def generate_data_types_markdown(types, enumerations, root=''):
|
||||
converted = [convert_jsdoc_array_to_ts(t) for t in types]
|
||||
primitives = {"string", "number", "boolean", "null", "undefined", "any", "object", "false", "true", "json", "function", "date", "{}"}
|
||||
result = []
|
||||
enum_names = {e['name'] for e in enumerations}
|
||||
for t in converted:
|
||||
base = t.rstrip('[]')
|
||||
dims = t[len(base):]
|
||||
if base in enum_names:
|
||||
used_enumerations.add(base)
|
||||
link = f"[Event_{base}]({root}../Enumeration/Event_{base}.md)"
|
||||
elif base in primitives or re.match(r"^['\"].*['\"]$", base) or re.match(r"^-?\d+(\.\d+)?$", base):
|
||||
link = base
|
||||
else:
|
||||
link = base
|
||||
result.append(link + dims)
|
||||
return " | ".join(result)
|
||||
|
||||
|
||||
def escape_text_outside_code_blocks(md):
|
||||
parts = re.split(r'(```.*?```)', md, flags=re.DOTALL)
|
||||
for i in range(0, len(parts), 2):
|
||||
parts[i] = parts[i].replace('<', '<').replace('>', '>')
|
||||
return "".join(parts)
|
||||
|
||||
|
||||
def generate_event_markdown(event, enumerations):
|
||||
name = event['name']
|
||||
desc = correct_description(event.get('description', ''))
|
||||
params = event.get('params', [])
|
||||
|
||||
md = f"# {name}\n\n{desc}\n\n"
|
||||
|
||||
# Parameters
|
||||
md += "## Parameters\n\n"
|
||||
if params:
|
||||
md += "| **Name** | **Data type** | **Description** |\n"
|
||||
md += "| --------- | ------------- | ----------- |\n"
|
||||
for p in params:
|
||||
t_md = generate_data_types_markdown(
|
||||
p.get('type', {}).get('names', []),
|
||||
enumerations
|
||||
)
|
||||
d = remove_line_breaks(correct_description(p.get('description', ''), isInTable=True))
|
||||
md += f"| {p['name']} | {t_md} | {d} |\n"
|
||||
md += "\n"
|
||||
else:
|
||||
md += "This event has no parameters.\n\n"
|
||||
|
||||
for ex in event.get('examples', []):
|
||||
code = remove_js_comments(ex).strip()
|
||||
md += f"```javascript\n{code}\n```\n\n"
|
||||
|
||||
return escape_text_outside_code_blocks(md)
|
||||
|
||||
|
||||
def generate_enumeration_markdown(enumeration, enumerations):
|
||||
"""
|
||||
Generates Markdown documentation for a 'typedef' doclet.
|
||||
This version only works with `enumeration['examples']` (an array of strings),
|
||||
ignoring any single `enumeration['examples']` field.
|
||||
"""
|
||||
enum_name = enumeration['name']
|
||||
|
||||
if enum_name not in used_enumerations:
|
||||
return None
|
||||
|
||||
description = enumeration.get('description', 'No description provided.')
|
||||
description = correct_description(description, '../')
|
||||
|
||||
# Only use the 'examples' array
|
||||
examples = enumeration.get('examples', [])
|
||||
|
||||
content = f"# Event_{enum_name}\n\n{description}\n\n"
|
||||
|
||||
parsed_type = enumeration['type'].get('parsedType')
|
||||
if not parsed_type:
|
||||
# If parsedType is missing, just list 'type.names' if available
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations)
|
||||
content += t_md + "\n\n"
|
||||
else:
|
||||
ptype = parsed_type['type']
|
||||
|
||||
# 1) Handle TypeUnion
|
||||
if ptype == 'TypeUnion':
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
for raw_t in enumeration['type']['names']:
|
||||
# Attempt linking
|
||||
if any(enum['name'] == raw_t for enum in enumerations):
|
||||
used_enumerations.add(raw_t)
|
||||
content += f"- [{raw_t}](../Enumeration/Event_{raw_t}.md)\n"
|
||||
else:
|
||||
content += f"- {raw_t}\n"
|
||||
|
||||
# 2) Handle TypeApplication (e.g. Object.<string, string>)
|
||||
elif ptype == 'TypeApplication':
|
||||
content += "## Type\n\nObject\n\n"
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
t_md = generate_data_types_markdown(type_names, enumerations)
|
||||
content += f"**Type:** {t_md}\n\n"
|
||||
|
||||
# 3) If properties are present, treat it like an object
|
||||
if enumeration.get('properties') is not None:
|
||||
content += generate_properties_markdown(enumeration['properties'], enumerations)
|
||||
|
||||
# 4) If it's neither TypeUnion nor TypeApplication, just output the type names
|
||||
if ptype not in ('TypeUnion', 'TypeApplication'):
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations)
|
||||
content += t_md + "\n\n"
|
||||
|
||||
# Process examples array
|
||||
if examples:
|
||||
if len(examples) > 1:
|
||||
content += "\n\n## Examples\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
cleaned_example = remove_js_comments(ex_line).strip()
|
||||
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
|
||||
content += f"```javascript\n{code}\n```\n"
|
||||
else:
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_events_summary(events):
|
||||
"""
|
||||
Create Events.md summary listing all events with their description.
|
||||
"""
|
||||
header = [
|
||||
"# Events\n\n",
|
||||
"| Event | Description |\n",
|
||||
"| ----- | ----------- |\n"
|
||||
]
|
||||
lines = [
|
||||
f"| [{ev['name']}](./{ev['name']}.md) | "
|
||||
f"{remove_line_breaks(correct_description(ev.get('description', ''), isInTable=True))} |\n"
|
||||
for ev in sorted(events, key=lambda e: e['name'])
|
||||
]
|
||||
return "".join(header + lines)
|
||||
|
||||
def generate_properties_markdown(properties, enumerations):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
|
||||
for prop in sorted(properties, key=lambda m: m['name']):
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description, isInTable=True))
|
||||
prop_types = prop['type']['names'] if prop.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(prop_types, enumerations)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
|
||||
# Escape outside code blocks
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def clean_editor_dir(editor_dir):
|
||||
for root, dirs, files in os.walk(editor_dir, topdown=False):
|
||||
for file in files:
|
||||
if not file.endswith(('.json')):
|
||||
os.remove(os.path.join(root, file))
|
||||
for dir in dirs:
|
||||
dir_path = os.path.join(root, dir)
|
||||
# remove empty folder
|
||||
if not os.listdir(dir_path):
|
||||
os.rmdir(dir_path)
|
||||
|
||||
def clean_enum_files(editor_dir: str):
|
||||
for root, _, files in os.walk(editor_dir, topdown=False):
|
||||
for file in files:
|
||||
if True == file.startswith('Event_') and False == file.endswith('.json'):
|
||||
os.remove(os.path.join(root, file))
|
||||
|
||||
def process_events(data, editor_dir):
|
||||
enumerations = []
|
||||
events = []
|
||||
|
||||
for doclet in data:
|
||||
kind = doclet.get('kind')
|
||||
if kind == 'typedef':
|
||||
enumerations.append(doclet)
|
||||
elif kind == 'event':
|
||||
events.append(doclet)
|
||||
|
||||
events_dir = f'{editor_dir}/Events'
|
||||
clean_editor_dir(events_dir)
|
||||
os.makedirs(events_dir, exist_ok=True)
|
||||
used_enumerations.clear()
|
||||
|
||||
# пишем события
|
||||
for ev in events:
|
||||
path = os.path.join(events_dir, f"{ev['name']}.md")
|
||||
write_markdown_file(path, generate_event_markdown(ev, enumerations))
|
||||
if not ev.get('examples'):
|
||||
missing_examples.append(os.path.relpath(path, events_dir))
|
||||
|
||||
# пишем перечисления, используемые событиями
|
||||
enum_dir = os.path.join(editor_dir, 'Enumeration')
|
||||
clean_enum_files(enum_dir)
|
||||
|
||||
os.makedirs(enum_dir, exist_ok=True)
|
||||
prev = -1
|
||||
while len(used_enumerations) != prev:
|
||||
prev = len(used_enumerations)
|
||||
for e in enumerations:
|
||||
if e['name'] in used_enumerations:
|
||||
generate_enumeration_markdown(e, enumerations)
|
||||
for e in enumerations:
|
||||
if e['name'] in used_enumerations:
|
||||
path = os.path.join(enum_dir, f"Event_{e['name']}.md")
|
||||
write_markdown_file(path, generate_enumeration_markdown(e, enumerations))
|
||||
if not e.get('examples'):
|
||||
missing_examples.append(os.path.relpath(path, editor_dir))
|
||||
|
||||
# events summary
|
||||
write_markdown_file(os.path.join(events_dir, "Events.md"), generate_events_summary(events))
|
||||
|
||||
def generate_events(output_dir):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
if output_dir.endswith('/'):
|
||||
output_dir = output_dir[:-1]
|
||||
tmp = os.path.join(output_dir, 'tmp_json')
|
||||
|
||||
generate_docs_events_json.generate(tmp, md=True)
|
||||
|
||||
for editor_name, folder in editors.items():
|
||||
data = load_json(os.path.join(tmp, f"{editor_name}.json"))
|
||||
process_events(data, os.path.join(output_dir, folder))
|
||||
|
||||
shutil.rmtree(tmp)
|
||||
print("Done. Missing examples:", missing_examples)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate events documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
nargs="?",
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/plugin-and-macros/interacting-with-editors/",
|
||||
help="Output directory"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
generate_events(args.destination)
|
||||
114
scripts/sdkjs_common/jsdoc/plugins/generate_docs_methods_json.py
Normal file
114
scripts/sdkjs_common/jsdoc/plugins/generate_docs_methods_json.py
Normal file
@ -0,0 +1,114 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
|
||||
# Configuration files
|
||||
configs = [
|
||||
"./config/methods/common.json",
|
||||
"./config/methods/word.json",
|
||||
"./config/methods/cell.json",
|
||||
"./config/methods/slide.json",
|
||||
"./config/methods/forms.json"
|
||||
]
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
def generate(output_dir, md=False):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Generate JSON documentation
|
||||
for config in configs:
|
||||
editor_name = config.split('/')[-1].replace('.json', '')
|
||||
output_file = os.path.join(output_dir, editor_name + ".json")
|
||||
command = f"npx jsdoc -c {config} -X > {output_file}"
|
||||
print(f"Generating {editor_name}.json: {command}")
|
||||
subprocess.run(command, shell=True)
|
||||
|
||||
common_doclets_file = os.path.join(output_dir, 'common.json')
|
||||
with open(common_doclets_file, 'r', encoding='utf-8') as f:
|
||||
common_doclets_json = json.dumps(json.load(f))
|
||||
os.remove(common_doclets_file)
|
||||
|
||||
# Append examples to JSON documentation
|
||||
for config in configs:
|
||||
if (config.find('common') != -1):
|
||||
continue
|
||||
|
||||
editor_name = config.split('/')[-1].replace('.json', '')
|
||||
example_folder_name = editor_name # name of folder with examples
|
||||
output_file = os.path.join(output_dir, editor_name + ".json")
|
||||
|
||||
# Read the JSON file
|
||||
with open(output_file, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
start_common_doclet_idx = len(data)
|
||||
data += json.loads(common_doclets_json)
|
||||
|
||||
# Modify JSON data
|
||||
for idx, doclet in enumerate(data):
|
||||
if idx >= start_common_doclet_idx:
|
||||
example_folder_name = 'common'
|
||||
elif editor_name == 'forms':
|
||||
example_folder_name = 'word'
|
||||
|
||||
if 'see' in doclet:
|
||||
if doclet['see'] is not None:
|
||||
doclet['see'][0] = doclet['see'][0].replace('{Editor}', example_folder_name.title())
|
||||
file_path = f'{root}/' + doclet['see'][0]
|
||||
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as see_file:
|
||||
example_content = see_file.read()
|
||||
|
||||
# Extract the first line as a comment if it exists
|
||||
lines = example_content.split('\n')
|
||||
if lines[0].startswith('//'):
|
||||
comment = lines[0] + '\n'
|
||||
code_content = '\n'.join(lines[1:])
|
||||
else:
|
||||
comment = ''
|
||||
code_content = example_content
|
||||
|
||||
doclet['examples'] = [remove_js_comments(comment) + code_content]
|
||||
|
||||
if md == False:
|
||||
document_type = editor_name
|
||||
if "forms" == document_type:
|
||||
document_type = "pdf"
|
||||
doclet['description'] = doclet['description'] + f'\n\n## Try it\n\n ```js document-builder={{"documentType": "{document_type}"}}\n{code_content}\n```'
|
||||
|
||||
# Write the modified JSON file back
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
print("Documentation generation for plugin methods completed.")
|
||||
|
||||
def remove_builder_lines(text):
|
||||
lines = text.splitlines() # Split text into lines
|
||||
filtered_lines = [line for line in lines if not line.strip().startswith("builder.")]
|
||||
return "\n".join(filtered_lines)
|
||||
|
||||
def remove_js_comments(text):
|
||||
# Remove single-line comments, leaving text after //
|
||||
text = re.sub(r'^\s*//\s?', '', text, flags=re.MULTILINE)
|
||||
# Remove multi-line comments, leaving text after /*
|
||||
text = re.sub(r'/\*\s*|\s*\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/office-js-api-declarations/office-js-api-plugins"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
651
scripts/sdkjs_common/jsdoc/plugins/generate_docs_methods_md.py
Normal file
651
scripts/sdkjs_common/jsdoc/plugins/generate_docs_methods_md.py
Normal file
@ -0,0 +1,651 @@
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_methods_json
|
||||
|
||||
# Configuration files
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../..'))
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
|
||||
cur_editor_name = None
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def write_markdown_file(file_path, content):
|
||||
with open(file_path, 'w', encoding='utf-8') as md_file:
|
||||
md_file.write(content)
|
||||
|
||||
def remove_js_comments(text):
|
||||
text = re.sub(r'^\s*//.*$', '', text, flags=re.MULTILINE) # single-line
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL) # multi-line
|
||||
return text.strip()
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
Finds patterns like {@link ...} and replaces them with Markdown links.
|
||||
If the prefix 'global#' is found, a link to a typedef is generated,
|
||||
otherwise, a link to a class method is created.
|
||||
For a method, if an alias is not specified, the name is left in the format 'Class#Method'.
|
||||
"""
|
||||
reserved_links = {
|
||||
'/docbuilder/global#ShapeType': f"{'../../../../../' if root == '' else '../../../../' if root == '../' else root}docs/office-api/usage-api/text-document-api/Enumeration/ShapeType.md",
|
||||
'/plugin/config': 'https://api.onlyoffice.com/docs/plugin-and-macros/structure/configuration/',
|
||||
'/docbuilder/basic': 'https://api.onlyoffice.com/docs/office-api/usage-api/text-document-api/'
|
||||
}
|
||||
|
||||
def replace_link(match):
|
||||
content = match.group(1).strip() # Example: "/docbuilder/global#ShapeType shape type" or "global#ErrorValue ErrorValue"
|
||||
parts = content.split()
|
||||
ref = parts[0]
|
||||
label = parts[1] if len(parts) > 1 else None
|
||||
|
||||
if ref.startswith('/'):
|
||||
# Handle reserved links using mapping
|
||||
if ref in reserved_links:
|
||||
url = reserved_links[ref]
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
else:
|
||||
# If the link is not in the mapping, return the original construction
|
||||
return match.group(0)
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
used_enumerations.add(typedef_name)
|
||||
display_text = label if label else typedef_name
|
||||
return f"[{display_text}]({root}Enumeration/{typedef_name}.md)"
|
||||
elif ref.startswith("https"):
|
||||
display_text = label if label else ref # Keep the full notation, e.g., "Api#CreateSlide"
|
||||
return f"[{display_text}]({ref})"
|
||||
else:
|
||||
# Handle links to class methods like ClassName#MethodName
|
||||
try:
|
||||
class_name, method_name = ref.split("#")
|
||||
except ValueError:
|
||||
return match.group(0)
|
||||
display_text = label if label else ref # Keep the full notation, e.g., "Api#CreateSlide"
|
||||
return f"[{display_text}]({root}{class_name}/Methods/{method_name}.md)"
|
||||
|
||||
return re.sub(r'{@link\s+([^}]+)}', replace_link, text)
|
||||
|
||||
def correct_description(string, root='', isInTable=False):
|
||||
"""
|
||||
Cleans or transforms specific tags in the doclet description:
|
||||
- <b> => ** (bold text)
|
||||
- <note>...</note> => 💡 ...
|
||||
- {@link ...} is replaced with a Markdown link
|
||||
- If the description is missing, returns a default value.
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
string = string.replace('\r', '\\\n')
|
||||
# Replace <b> tags with Markdown bold formatting
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
# Replace <note> tags with an icon and text
|
||||
string = re.sub(r'<note>(.*?)</note>', r'💡 \1', string, flags=re.DOTALL)
|
||||
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
|
||||
def correct_default_value(value, enumerations, classes):
|
||||
if value is None or value == '':
|
||||
return ''
|
||||
|
||||
if value == True:
|
||||
value = "true"
|
||||
elif value == False:
|
||||
value = "false"
|
||||
else:
|
||||
value = str(value)
|
||||
|
||||
return generate_data_types_markdown([value], enumerations, classes)
|
||||
|
||||
def remove_line_breaks(string):
|
||||
return re.sub(r'[\r\n]+', ' ', string)
|
||||
|
||||
# Convert Array.<T> => T[] (including nested arrays).
|
||||
def convert_jsdoc_array_to_ts(type_str: str) -> str:
|
||||
"""
|
||||
Recursively replaces 'Array.<T>' with 'T[]',
|
||||
handling nested arrays like 'Array.<Array.<string>>' => 'string[][]'.
|
||||
"""
|
||||
pattern = re.compile(r'Array\.<([^>]+)>')
|
||||
|
||||
while True:
|
||||
match = pattern.search(type_str)
|
||||
if not match:
|
||||
break
|
||||
|
||||
inner_type = match.group(1).strip()
|
||||
# Recursively convert inner parts
|
||||
inner_type = convert_jsdoc_array_to_ts(inner_type)
|
||||
|
||||
# Replace the outer Array.<...> with ...[]
|
||||
type_str = (
|
||||
type_str[:match.start()]
|
||||
+ f"{inner_type}[]"
|
||||
+ type_str[match.end():]
|
||||
)
|
||||
|
||||
return type_str
|
||||
|
||||
def escape_text_outside_code_blocks(markdown: str) -> str:
|
||||
"""
|
||||
Splits content by fenced code blocks, escapes MDX-unsafe characters
|
||||
(<, >, {, }) only in the text outside those code blocks.
|
||||
"""
|
||||
# A regex to capture fenced code blocks with ```
|
||||
parts = re.split(r'(```.*?```)', markdown, flags=re.DOTALL)
|
||||
|
||||
# Even indices (0, 2, 4, ...) are outside code blocks,
|
||||
# odd indices (1, 3, 5, ...) are actual code blocks.
|
||||
for i in range(0, len(parts), 2):
|
||||
text = (parts[i]
|
||||
.replace('<', '<')
|
||||
.replace('>', '>')
|
||||
.replace('{', '{')
|
||||
.replace('}', '}'))
|
||||
parts[i] = escape_brackets_in_quotes(text)
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
def escape_brackets_in_quotes(text: str) -> str:
|
||||
return re.sub(
|
||||
r"(['\"])(.*?)(?<!\\)\1",
|
||||
lambda m: m.group(1)
|
||||
+ m.group(2).replace('[', r'\[').replace(']', r'\]')
|
||||
+ m.group(1),
|
||||
text
|
||||
)
|
||||
|
||||
def get_base_type(ts_type: str) -> str:
|
||||
"""
|
||||
Given a TypeScript-like type (e.g. "Drawing[][]"), return the
|
||||
'base' portion by stripping trailing "[]". For "Drawing[][]",
|
||||
returns "Drawing". For "Array.<Drawing>", you'd convert it first
|
||||
to "Drawing[]" then return "Drawing".
|
||||
"""
|
||||
while ts_type.endswith('[]'):
|
||||
ts_type = ts_type[:-2]
|
||||
return ts_type
|
||||
|
||||
def generate_data_types_markdown(types, enumerations, classes, root='../'):
|
||||
"""
|
||||
1) Converts each type from JSDoc (e.g., Array.<T>) to T[].
|
||||
2) Processes union types by splitting them using '|'.
|
||||
3) Supports multidimensional arrays, e.g., (string|ApiRange|number)[].
|
||||
4) If the base type matches the name of an enumeration or class, generates a link.
|
||||
5) The final types are joined using " | ".
|
||||
"""
|
||||
# Convert each type from JSDoc format to TypeScript format (e.g., T[])
|
||||
converted = [convert_jsdoc_array_to_ts(t) for t in types]
|
||||
|
||||
# Set of primitive types
|
||||
primitive_types = {"string", "number", "boolean", "null", "undefined", "any", "object", "false", "true", "json", "function", "date", "{}"}
|
||||
|
||||
def is_primitive(type):
|
||||
if (type.lower() in primitive_types or
|
||||
(type.startswith('"') and type.endswith('"')) or
|
||||
(type.startswith("'") and type.endswith("'")) or
|
||||
type.replace('.', '', 1).isdigit() or
|
||||
(type.startswith('-') and type[1:].replace('.', '', 1).isdigit())):
|
||||
return True
|
||||
return False
|
||||
|
||||
def link_if_known(ts_type):
|
||||
ts_type = ts_type.strip()
|
||||
# Count the number of array dimensions, e.g., "[][]" has 2 dimensions
|
||||
array_dims = 0
|
||||
while ts_type.endswith("[]"):
|
||||
array_dims += 1
|
||||
ts_type = ts_type[:-2].strip()
|
||||
|
||||
# Process generic types, e.g., Object.<string, editorType>
|
||||
if ".<" in ts_type and ts_type.endswith(">"):
|
||||
import re
|
||||
m = re.match(r'^(.*?)\.<(.*)>$', ts_type)
|
||||
if m:
|
||||
base_part = m.group(1).strip()
|
||||
generic_args_str = m.group(2).strip()
|
||||
# Process the base part of the type
|
||||
found = False
|
||||
for enum in enumerations:
|
||||
if enum['name'] == base_part:
|
||||
used_enumerations.add(base_part)
|
||||
base_result = f"[{base_part}]({root}Enumeration/{base_part}.md)"
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if base_part in classes:
|
||||
base_result = f"[{base_part}]({root}{base_part}/{base_part}.md)"
|
||||
elif is_primitive(base_part):
|
||||
base_result = base_part
|
||||
elif cur_editor_name == "forms":
|
||||
base_result = f"[{base_part}]({root}../text-document-api/{base_part}/{base_part}.md)"
|
||||
else:
|
||||
print(f"Unknown type encountered: {base_part}")
|
||||
base_result = base_part
|
||||
# Split the generic parameters by commas and process each recursively
|
||||
generic_args = [link_if_known(x) for x in generic_args_str.split(",")]
|
||||
result = base_result + ".<" + ", ".join(generic_args) + ">"
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# Process union types: if the type is enclosed in parentheses
|
||||
if ts_type.startswith("(") and ts_type.endswith(")"):
|
||||
inner = ts_type[1:-1].strip()
|
||||
subtypes = [sub.strip() for sub in inner.split("|")]
|
||||
if len(subtypes) == 1:
|
||||
result = link_if_known(subtypes[0])
|
||||
else:
|
||||
processed = [link_if_known(subtype) for subtype in subtypes]
|
||||
result = "(" + " | ".join(processed) + ")"
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# If not a generic or union type – process the base type
|
||||
else:
|
||||
base = ts_type
|
||||
found = False
|
||||
for enum in enumerations:
|
||||
if enum['name'] == base:
|
||||
used_enumerations.add(base)
|
||||
result = f"[{base}]({root}Enumeration/{base}.md)"
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if base in classes:
|
||||
result = f"[{base}]({root}{base}/{base}.md)"
|
||||
elif is_primitive(base):
|
||||
result = base
|
||||
elif cur_editor_name == "forms":
|
||||
result = f"[{base}]({root}../text-document-api/{base}/{base}.md)"
|
||||
else:
|
||||
print(f"Unknown type encountered: {base}")
|
||||
result = base
|
||||
result += "[]" * array_dims
|
||||
return result
|
||||
|
||||
# Apply link_if_known to each converted type
|
||||
linked = [link_if_known(ts_t) for ts_t in converted]
|
||||
|
||||
# Join results using " | "
|
||||
param_types_md = r' | '.join(linked)
|
||||
param_types_md = param_types_md.replace("|", r"\|")
|
||||
|
||||
# Escape remaining angle brackets for generics
|
||||
def replace_leftover_generics(match):
|
||||
element = match.group(1).strip()
|
||||
return f"<{element}>"
|
||||
|
||||
param_types_md = re.sub(r'<([^<>]+)>', replace_leftover_generics, param_types_md)
|
||||
|
||||
return param_types_md
|
||||
|
||||
def generate_class_markdown(class_name, methods, properties, enumerations, classes):
|
||||
content = f"# {class_name}\n\nRepresents the {class_name} class.\n\n"
|
||||
|
||||
content += generate_properties_markdown(properties, enumerations, classes)
|
||||
|
||||
content += "\n## Methods\n\n"
|
||||
content += "| Method | Returns | Description |\n"
|
||||
content += "| ------ | ------- | ----------- |\n"
|
||||
|
||||
for method in sorted(methods, key=lambda m: m['name']):
|
||||
method_name = method['name']
|
||||
|
||||
# Get the type of return values
|
||||
returns = method.get('returns', [])
|
||||
if returns:
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
returns_markdown = generate_data_types_markdown(return_type_list, enumerations, classes, '../')
|
||||
else:
|
||||
returns_markdown = "None"
|
||||
|
||||
# Processing the method description
|
||||
description = remove_line_breaks(correct_description(method.get('description', 'No description provided.'), '../', True))
|
||||
|
||||
# Form a link to the method document
|
||||
method_link = f"[{method_name}](./{method_name}.md)"
|
||||
|
||||
content += f"| {method_link} | {returns_markdown} | {description} |\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_method_markdown(method, enumerations, classes):
|
||||
"""
|
||||
Generates Markdown for a method doclet, relying only on `method['examples']`
|
||||
(array of strings). Ignores any single `method['example']` field.
|
||||
"""
|
||||
|
||||
method_name = method['name']
|
||||
description = method.get('description', 'No description provided.')
|
||||
description = correct_description(description, '../')
|
||||
params = method.get('params', [])
|
||||
returns = method.get('returns', [])
|
||||
memberof = method.get('memberof', '')
|
||||
|
||||
# Use the 'examples' array only
|
||||
examples = method.get('examples', [])
|
||||
|
||||
content = f"# {method_name}\n\n{description}\n\n"
|
||||
|
||||
# Syntax
|
||||
param_list = ', '.join([param['name'] for param in params if '.' not in param['name']]) if params else ''
|
||||
content += f"## Syntax\n\n```javascript\nexpression.{method_name}({param_list});\n```\n\n"
|
||||
if memberof:
|
||||
content += f"`expression` - A variable that represents a [{memberof}](Methods.md) class.\n\n"
|
||||
|
||||
# Parameters
|
||||
content += "## Parameters\n\n"
|
||||
if params:
|
||||
content += "| **Name** | **Required/Optional** | **Data type** | **Default** | **Description** |\n"
|
||||
content += "| ------------- | ------------- | ------------- | ------------- | ------------- |\n"
|
||||
for param in params:
|
||||
param_name = param.get('name', 'Unnamed')
|
||||
param_types = param.get('type', {}).get('names', []) if param.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(param_types, enumerations, classes)
|
||||
param_desc = remove_line_breaks(correct_description(param.get('description', 'No description provided.'), '../', True))
|
||||
param_required = "Required" if not param.get('optional') else "Optional"
|
||||
param_default = correct_default_value(param.get('defaultvalue', ''), enumerations, classes)
|
||||
|
||||
content += f"| {param_name} | {param_required} | {param_types_md} | {param_default} | {param_desc} |\n"
|
||||
else:
|
||||
content += "This method doesn't have any parameters.\n"
|
||||
|
||||
# Returns
|
||||
content += "\n## Returns\n\n"
|
||||
if returns:
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
return_type_md = generate_data_types_markdown(return_type_list, enumerations, classes)
|
||||
content += return_type_md
|
||||
else:
|
||||
content += "This method doesn't return any data."
|
||||
|
||||
# Process examples array
|
||||
if examples:
|
||||
if len(examples) > 1:
|
||||
content += "\n\n## Examples\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
cleaned_example = remove_js_comments(ex_line).strip()
|
||||
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
|
||||
content += f"```javascript\n{code}\n```\n"
|
||||
else:
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_properties_markdown(properties, enumerations, classes, root='../'):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
|
||||
for prop in sorted(properties, key=lambda m: m['name']):
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description, isInTable=True))
|
||||
prop_types = prop['type']['names'] if prop.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(prop_types, enumerations, classes, root)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
|
||||
# Escape outside code blocks
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
"""
|
||||
Generates Markdown documentation for a 'typedef' doclet.
|
||||
This version only works with `enumeration['examples']` (an array of strings),
|
||||
ignoring any single `enumeration['examples']` field.
|
||||
"""
|
||||
enum_name = enumeration['name']
|
||||
|
||||
if enum_name not in used_enumerations:
|
||||
return None
|
||||
|
||||
description = enumeration.get('description', 'No description provided.')
|
||||
description = correct_description(description, '../')
|
||||
|
||||
# Only use the 'examples' array
|
||||
examples = enumeration.get('examples', [])
|
||||
|
||||
content = f"# {enum_name}\n\n{description}\n\n"
|
||||
|
||||
parsed_type = enumeration['type'].get('parsedType')
|
||||
if not parsed_type:
|
||||
# If parsedType is missing, just list 'type.names' if available
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += t_md + "\n\n"
|
||||
else:
|
||||
ptype = parsed_type['type']
|
||||
|
||||
# 1) Handle TypeUnion
|
||||
if ptype == 'TypeUnion':
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
for raw_t in enumeration['type']['names']:
|
||||
# Attempt linking
|
||||
if any(enum['name'] == raw_t for enum in enumerations):
|
||||
used_enumerations.add(raw_t)
|
||||
content += f"- [{raw_t}](../Enumeration/{raw_t}.md)\n"
|
||||
elif raw_t in classes:
|
||||
content += f"- [{raw_t}](../{raw_t}/{raw_t}.md)\n"
|
||||
else:
|
||||
content += f"- {raw_t}\n"
|
||||
|
||||
# 2) Handle TypeApplication (e.g. Object.<string, string>)
|
||||
elif ptype == 'TypeApplication':
|
||||
content += "## Type\n\nObject\n\n"
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += f"**Type:** {t_md}\n\n"
|
||||
|
||||
# 3) If properties are present, treat it like an object
|
||||
if enumeration.get('properties') is not None:
|
||||
content += generate_properties_markdown(enumeration['properties'], enumerations, classes)
|
||||
|
||||
# 4) If it's neither TypeUnion nor TypeApplication, just output the type names
|
||||
if ptype not in ('TypeUnion', 'TypeApplication'):
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += t_md + "\n\n"
|
||||
|
||||
# Process examples array
|
||||
if examples:
|
||||
if len(examples) > 1:
|
||||
content += "\n\n## Examples\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
cleaned_example = remove_js_comments(ex_line).strip()
|
||||
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
|
||||
content += f"```javascript\n{code}\n```\n"
|
||||
else:
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
def clean_methods_dir(methods_dir):
|
||||
for root, dirs, files in os.walk(methods_dir, topdown=False):
|
||||
for file in files:
|
||||
if not file.endswith(('.json')):
|
||||
os.remove(os.path.join(root, file))
|
||||
for dir in dirs:
|
||||
dir_path = os.path.join(root, dir)
|
||||
# remove empty folder
|
||||
if not os.listdir(dir_path):
|
||||
os.rmdir(dir_path)
|
||||
|
||||
def clean_enum_files(editor_dir: str):
|
||||
for root, _, files in os.walk(editor_dir, topdown=False):
|
||||
for file in files:
|
||||
if False == file.startswith('Event_') and False == file.endswith('.json'):
|
||||
os.remove(os.path.join(root, file))
|
||||
|
||||
def process_doclets(data, output_dir, editor_name):
|
||||
global cur_editor_name
|
||||
cur_editor_name = editor_name
|
||||
|
||||
classes = {}
|
||||
classes_props = {}
|
||||
enumerations = []
|
||||
editor_dir = os.path.join(output_dir, editors[editor_name])
|
||||
methods_dir = os.path.join(output_dir, editors[editor_name], 'Methods')
|
||||
|
||||
clean_methods_dir(methods_dir)
|
||||
os.makedirs(methods_dir, exist_ok=True)
|
||||
|
||||
for doclet in data:
|
||||
if doclet['kind'] == 'class':
|
||||
class_name = doclet['name']
|
||||
if class_name:
|
||||
if class_name not in classes:
|
||||
classes[class_name] = []
|
||||
classes_props[class_name] = doclet.get('properties', None)
|
||||
elif doclet['kind'] == 'function':
|
||||
class_name = doclet.get('memberof')
|
||||
if class_name:
|
||||
if class_name not in classes:
|
||||
classes[class_name] = []
|
||||
classes[class_name].append(doclet)
|
||||
elif doclet['kind'] == 'typedef':
|
||||
enumerations.append(doclet)
|
||||
|
||||
# Process api methods
|
||||
class_name = 'Api'
|
||||
methods = classes[class_name]
|
||||
# Write class file
|
||||
class_content = generate_class_markdown(
|
||||
class_name,
|
||||
methods,
|
||||
classes_props[class_name],
|
||||
enumerations,
|
||||
classes
|
||||
)
|
||||
write_markdown_file(os.path.join(methods_dir, f"Methods.md"), class_content)
|
||||
|
||||
# Write method files
|
||||
for method in methods:
|
||||
method_file_path = os.path.join(methods_dir, f"{method['name']}.md")
|
||||
method_content = generate_method_markdown(method, enumerations, classes)
|
||||
write_markdown_file(method_file_path, method_content)
|
||||
|
||||
if not method.get('examples', ''):
|
||||
missing_examples.append(os.path.relpath(method_file_path, output_dir))
|
||||
|
||||
# Process enumerations
|
||||
enum_dir = os.path.join(editor_dir, 'Enumeration')
|
||||
clean_enum_files(enum_dir)
|
||||
os.makedirs(enum_dir, exist_ok=True)
|
||||
|
||||
# idle run
|
||||
prev_used_count = -1
|
||||
while len(used_enumerations) != prev_used_count:
|
||||
prev_used_count = len(used_enumerations)
|
||||
for enum in [e for e in enumerations if e['name'] in used_enumerations]:
|
||||
enum_content = generate_enumeration_markdown(enum, enumerations, classes)
|
||||
|
||||
for enum in enumerations:
|
||||
enum_file_path = os.path.join(enum_dir, f"{enum['name']}.md")
|
||||
enum_content = generate_enumeration_markdown(enum, enumerations, classes)
|
||||
if enum_content is None:
|
||||
continue
|
||||
|
||||
write_markdown_file(enum_file_path, enum_content)
|
||||
if not enum.get('examples', ''):
|
||||
missing_examples.append(os.path.relpath(enum_file_path, output_dir))
|
||||
|
||||
def generate(output_dir):
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
print('Generating Markdown documentation...')
|
||||
|
||||
if output_dir[-1] == '/':
|
||||
output_dir = output_dir[:-1]
|
||||
|
||||
generate_docs_methods_json.generate(output_dir + '/tmp_json', md=True)
|
||||
for editor_name, folder_name in editors.items():
|
||||
input_file = os.path.join(output_dir + '/tmp_json', editor_name + ".json")
|
||||
|
||||
data = load_json(input_file)
|
||||
used_enumerations.clear()
|
||||
process_doclets(data, output_dir, editor_name)
|
||||
|
||||
shutil.rmtree(output_dir + '/tmp_json')
|
||||
print('Done')
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate documentation")
|
||||
parser.add_argument(
|
||||
"destination",
|
||||
type=str,
|
||||
help="Destination directory for the generated documentation",
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/plugin-and-macros/interacting-with-editors/" # Default value
|
||||
)
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
print("START_MISSING_EXAMPLES")
|
||||
print(",".join(missing_examples))
|
||||
print("END_MISSING_EXAMPLES")
|
||||
@ -14,6 +14,15 @@ def is_exist_in_array(projects, proj):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_full_projects_list(json_data, list):
|
||||
result = []
|
||||
for rec in list:
|
||||
if rec in json_data:
|
||||
result += get_full_projects_list(json_data, json_data[rec])
|
||||
else:
|
||||
result.append(rec)
|
||||
return result
|
||||
|
||||
def adjust_project_params(params):
|
||||
ret_params = params
|
||||
|
||||
@ -86,13 +95,9 @@ def get_projects(pro_json_path, platform):
|
||||
|
||||
# check aliases to modules
|
||||
records_src = data[module]
|
||||
records = []
|
||||
records = get_full_projects_list(data, records_src)
|
||||
|
||||
for rec in records_src:
|
||||
if rec in data:
|
||||
records += data[rec]
|
||||
else:
|
||||
records.append(rec)
|
||||
#print(records)
|
||||
|
||||
for rec in records:
|
||||
params = []
|
||||
@ -128,7 +133,7 @@ def get_projects(pro_json_path, platform):
|
||||
is_needed_platform_exist = False
|
||||
for pl in platform_records:
|
||||
if is_exist_in_array(params, pl):
|
||||
is_needed_platform_exist = True;
|
||||
is_needed_platform_exist = True
|
||||
break
|
||||
|
||||
# if one config exists => all needed must exists
|
||||
@ -139,7 +144,7 @@ def get_projects(pro_json_path, platform):
|
||||
if is_exist_in_array(platform_records, item):
|
||||
continue
|
||||
is_needed_config_exist = True
|
||||
break;
|
||||
break
|
||||
|
||||
if is_needed_platform_exist:
|
||||
if not is_exist_in_array(params, platform):
|
||||
@ -159,6 +164,18 @@ def get_projects(pro_json_path, platform):
|
||||
if is_append:
|
||||
result.append(root_dir + record)
|
||||
|
||||
# delete duplicates
|
||||
old_results = result
|
||||
result = []
|
||||
|
||||
map_results = set()
|
||||
for item in old_results:
|
||||
proj = item.replace("\\", "/")
|
||||
if proj in map_results:
|
||||
continue
|
||||
map_results.add(proj)
|
||||
result.append(proj)
|
||||
|
||||
if is_log:
|
||||
print(result)
|
||||
return result
|
||||
|
||||
25
sln.json
25
sln.json
@ -1,6 +1,10 @@
|
||||
{
|
||||
"root" : "../",
|
||||
|
||||
"spell" : [
|
||||
"[win,linux,mac]core/Common/3dParty/hunspell/qt/hunspell.pro"
|
||||
],
|
||||
|
||||
"core" : [
|
||||
|
||||
"core/Common/3dParty/cryptopp/project/cryptopp.pro",
|
||||
@ -15,15 +19,17 @@
|
||||
"core/PdfFile/PdfFile.pro",
|
||||
"core/DjVuFile/DjVuFile.pro",
|
||||
"core/XpsFile/XpsFile.pro",
|
||||
"core/OFDFile/OFDFile.pro",
|
||||
"core/HtmlFile2/HtmlFile2.pro",
|
||||
"core/Fb2File/Fb2File.pro",
|
||||
"core/EpubFile/CEpubFile.pro",
|
||||
|
||||
"core/HtmlRenderer/htmlrenderer.pro",
|
||||
"core/HwpFile/HWPFile.pro",
|
||||
|
||||
"core/Apple/IWork.pro",
|
||||
|
||||
"core/DocxRenderer/DocxRenderer.pro",
|
||||
|
||||
"core/DesktopEditor/doctrenderer/doctrenderer.pro",
|
||||
"core/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_func_lib.pro",
|
||||
|
||||
"[!no_x2t]core/OOXML/Projects/Linux/DocxFormatLib/DocxFormatLib.pro",
|
||||
"[!no_x2t]core/OOXML/Projects/Linux/PPTXFormatLib/PPTXFormatLib.pro",
|
||||
@ -51,15 +57,19 @@
|
||||
|
||||
"[win,linux,mac,!linux_arm64]core/OfficeCryptReader/ooxml_crypt/ooxml_crypt.pro",
|
||||
|
||||
"spell",
|
||||
|
||||
"[win,linux,mac,!no_tests]core/DesktopEditor/vboxtester/vboxtester.pro",
|
||||
"[win,linux,mac,!no_tests]core/Test/Applications/StandardTester/standardtester.pro",
|
||||
"[win,linux,mac,!no_tests]core/Test/Applications/x2tTester/x2ttester.pro",
|
||||
"[win,linux,mac,!no_tests]core/Test/Applications/MetafileTester/MetafileTester.pro"
|
||||
"[win,linux,mac,!no_tests]core/Test/Applications/MetafileTester/MetafileTester.pro",
|
||||
"[win,linux,mac,!no_tests]core/Common/3dParty/hunspell/test/test.pro"
|
||||
|
||||
],
|
||||
|
||||
"builder" : [
|
||||
"core"
|
||||
"core",
|
||||
"core/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_func_lib.pro"
|
||||
],
|
||||
|
||||
"server" : [
|
||||
@ -70,13 +80,8 @@
|
||||
"[win,linux]desktop-sdk/ChromiumBasedEditors/videoplayerlib/videoplayerlib.pro"
|
||||
],
|
||||
|
||||
"spell" : [
|
||||
"[win,linux,mac]core/Common/3dParty/hunspell/qt/hunspell.pro"
|
||||
],
|
||||
|
||||
"desktop" : [
|
||||
"core",
|
||||
"spell",
|
||||
"multimedia",
|
||||
|
||||
"core/DesktopEditor/xmlsec/src/ooxmlsignature.pro",
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"browser" : "chrome",
|
||||
"browserUrl" : "C:/Program Files/Google/Chrome/Application/chrome.exe"
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"browser" : "firefox",
|
||||
"browserUrl" : "C:/Program Files/Mozilla Firefox/firefox.exe"
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
|
||||
os.environ["PUPPETEER_SKIP_CHROMIUM_DOWNLOAD"] = "true"
|
||||
base.cmd("npm", ["i", "puppeteer"])
|
||||
@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
import glob
|
||||
import json
|
||||
|
||||
def get_tests_in_dir(directory):
|
||||
files = []
|
||||
for file in glob.glob(directory + "/*.js"):
|
||||
if base.is_file(file):
|
||||
files.append(file)
|
||||
elif is_dir(file):
|
||||
files += get_tests_in_dir(file)
|
||||
return files
|
||||
|
||||
params = sys.argv[1:]
|
||||
if (0 == len(params)):
|
||||
print("use: run.py path_to_config [path_to_test]")
|
||||
exit(0)
|
||||
|
||||
config_path = params[0]
|
||||
test_file = "./tests"
|
||||
|
||||
if (1 < len(params)):
|
||||
test_file = params[1]
|
||||
|
||||
tests_array = [test_file]
|
||||
if base.is_dir(test_file):
|
||||
tests_array = get_tests_in_dir(test_file)
|
||||
|
||||
config_content = "{}"
|
||||
with open(config_path, "r") as config_path_loader:
|
||||
config_content = config_path_loader.read()
|
||||
|
||||
print(config_content)
|
||||
|
||||
config = json.loads(config_content)
|
||||
os.environ["PUPPETEER_SKIP_CHROMIUM_DOWNLOAD"] = "true"
|
||||
if "browser" in config:
|
||||
print("browser: " + config["browser"])
|
||||
os.environ["PUPPETEER_PRODUCT"] = config["browser"]
|
||||
|
||||
if "browserUrl" in config:
|
||||
print("browserUrl: " + config["browserUrl"])
|
||||
os.environ["PUPPETEER_EXECUTABLE_PATH"] = config["browserUrl"]
|
||||
|
||||
if not base.is_dir("./work_directory"):
|
||||
base.create_dir("./work_directory")
|
||||
base.create_dir("./work_directory/cache")
|
||||
base.create_dir("./work_directory/downloads")
|
||||
|
||||
for test in tests_array:
|
||||
print("run test: " + test)
|
||||
run_file = test + ".runned.js"
|
||||
base.copy_file("./tester.js", run_file)
|
||||
test_content = base.readFile(test)
|
||||
test_content = test_content.replace("await Tester.", "Tester.")
|
||||
test_content = test_content.replace("Tester.", "await Tester.")
|
||||
base.replaceInFile(run_file, "\"%%CODE%%\"", test_content)
|
||||
base.cmd("node", [run_file])
|
||||
base.delete_file(run_file)
|
||||
@ -1,171 +0,0 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const pathfs = require('path')
|
||||
const fs = require('fs');
|
||||
|
||||
function TesterImpl()
|
||||
{
|
||||
this.browser = null;
|
||||
this.page = null;
|
||||
this.width = 1500;
|
||||
this.height = 800;
|
||||
this.pixelRatio = 1;
|
||||
|
||||
this.cacheDir = pathfs.resolve("./work_directory/cache");
|
||||
this.downloadsDir = pathfs.resolve("./work_directory/downloads");
|
||||
this.downloadCounter = 0;
|
||||
|
||||
this.load = async function(url)
|
||||
{
|
||||
const head = { x: 100, y: 200 };
|
||||
this.browser = await puppeteer.launch({
|
||||
headless: false,
|
||||
product: process.env["PUPPETEER_PRODUCT"],
|
||||
args: [
|
||||
"--disable-infobars",
|
||||
`--window-size=${this.width+head.x},${this.height+head.y}`,
|
||||
"--disk-cache-dir=" + this.cacheDir
|
||||
],
|
||||
defaultViewport : {width: this.width, height: this.height, deviceScaleFactor : this.pixelRatio }
|
||||
});
|
||||
|
||||
this.page = await this.browser.newPage();
|
||||
await this.page.setViewport({ width: this.width, height: this.height });
|
||||
let waitObject = (process.env["PUPPETEER_PRODUCT"] === "firefox") ? { waitUntil: "networkidle0", timeout: 15000 } : {};
|
||||
await this.page.goto(url + "&autotest=enabled", waitObject);
|
||||
console.log("[tester] pageLoaded");
|
||||
return this.page;
|
||||
};
|
||||
|
||||
this.close = async function(nosleep)
|
||||
{
|
||||
if (true !== nosleep)
|
||||
await this.waitAutosave();
|
||||
await this.browser.close();
|
||||
};
|
||||
|
||||
this.sleep = async function(ms)
|
||||
{
|
||||
return await new Promise(resolve => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
this.waitEditor = async function()
|
||||
{
|
||||
// TODO: wait first onEndRecalculate
|
||||
await this.sleep(5000);
|
||||
console.log("[tester] editorReady");
|
||||
};
|
||||
|
||||
this.waitAutosave = async function()
|
||||
{
|
||||
await this.sleep(5000);
|
||||
};
|
||||
|
||||
this.evaluateInMainFrame = async function(code)
|
||||
{
|
||||
return await this.page.evaluate(code);
|
||||
};
|
||||
this.evaluateInEditorFrame = async function(code)
|
||||
{
|
||||
const frame = await this.page.frames().find(frame => frame.name() === 'frameEditor');
|
||||
if (!frame)
|
||||
return;
|
||||
return await frame.evaluate(code);
|
||||
};
|
||||
|
||||
this.click = async function(id)
|
||||
{
|
||||
let res = await this.evaluateInEditorFrame("document.getElementById(\"" + id + "\").click(); \"[tester] clicked: " + id + "\"");
|
||||
//console.log(res);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.mouseClick = async function(x, y, options)
|
||||
{
|
||||
let res = await this.page.mouse.click(x, y, options);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.eval = async function(code)
|
||||
{
|
||||
let res = await this.evaluateInEditorFrame(code);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.keyDown = async function(key)
|
||||
{
|
||||
// https://pptr.dev/api/puppeteer.keyinput
|
||||
let res = await this.page.keyboard.down(key);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.keyUp = async function(key)
|
||||
{
|
||||
// https://pptr.dev/api/puppeteer.keyinput
|
||||
let res = await this.page.keyboard.up(key);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.keyClick = async function(key)
|
||||
{
|
||||
// https://pptr.dev/api/puppeteer.keyinput
|
||||
let res = await this.page.keyboard.down(key);
|
||||
res = await this.page.keyboard.up(key);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.keyPress = async function(key)
|
||||
{
|
||||
// https://pptr.dev/api/puppeteer.keyinput
|
||||
let res = await this.page.keyboard.press(key);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.input = async function(text)
|
||||
{
|
||||
let res = await this.page.keyboard.type(text);
|
||||
await this.sleep(200);
|
||||
return res;
|
||||
};
|
||||
|
||||
this.downloadFile = async function(format, path)
|
||||
{
|
||||
const tmpDir = pathfs.resolve(this.downloadsDir, "./tmp" + this.downloadCounter++);
|
||||
fs.mkdirSync(tmpDir);
|
||||
|
||||
// emulate download
|
||||
const client = await this.page.target().createCDPSession();
|
||||
await client.send("Page.setDownloadBehavior", {
|
||||
behavior: "allow",
|
||||
downloadPath: tmpDir
|
||||
});
|
||||
|
||||
await this.evaluateInEditorFrame("document.querySelectorAll('[data-layout-name=\"toolbar-file\"]')[0].click();");
|
||||
await this.sleep(200);
|
||||
await this.evaluateInEditorFrame("document.getElementsByClassName(\"svg-format-" + format + "\")[0].click();");
|
||||
await this.sleep(200);
|
||||
await this.evaluateInEditorFrame("document.getElementById(\"fm-btn-return\").click();");
|
||||
|
||||
await this.sleep(2000);
|
||||
|
||||
const files = fs.readdirSync(tmpDir);
|
||||
fs.copyFileSync(pathfs.resolve(tmpDir, "./" + files[0]), pathfs.resolve(path));
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
};
|
||||
}
|
||||
|
||||
const Tester = new TesterImpl;
|
||||
|
||||
try {
|
||||
(async () => {
|
||||
"%%CODE%%"
|
||||
})();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
Tester.load("path_to_file");
|
||||
Tester.waitEditor();
|
||||
|
||||
// down Enter
|
||||
Tester.keyClick("Enter");
|
||||
|
||||
// type text
|
||||
Tester.input("Hello World!");
|
||||
|
||||
Tester.keyPress("ArrowLeft");
|
||||
Tester.keyDown("Shift");
|
||||
for (let i = 0; i < 5; i++)
|
||||
Tester.keyPress("ArrowLeft");
|
||||
Tester.keyUp("Shift");
|
||||
|
||||
// bold
|
||||
Tester.click("id-toolbar-btn-bold");
|
||||
// italic
|
||||
Tester.mouseClick(115, 105);
|
||||
|
||||
// if needed
|
||||
Tester.waitAutosave();
|
||||
|
||||
Tester.downloadFile("docx", "./work_directory/new.docx")
|
||||
Tester.downloadFile("odt", "./work_directory/new.odt")
|
||||
|
||||
Tester.close(true);
|
||||
@ -68,6 +68,7 @@ AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLR = AVS_OFFICESTUDIO_FILE_CROS
|
||||
AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLRMenu = AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0007
|
||||
AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLRCanvas = AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0008
|
||||
AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA = AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0009
|
||||
AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD = AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x000a
|
||||
|
||||
AVS_OFFICESTUDIO_FILE_IMAGE = 0x0400
|
||||
AVS_OFFICESTUDIO_FILE_IMAGE_JPG = AVS_OFFICESTUDIO_FILE_IMAGE + 0x0001
|
||||
|
||||
114
tools/common/desktop_templates.py
Normal file
114
tools/common/desktop_templates.py
Normal file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
import glob
|
||||
import base64
|
||||
|
||||
sys.stdin.reconfigure(encoding='utf-8')
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
base.configure_common_apps()
|
||||
|
||||
def change_property(data_src, name, value):
|
||||
data = data_src
|
||||
creator_open = "<dc:" + name + ">"
|
||||
creator_close = "</dc:" + name + ">"
|
||||
open_tag_pos = data.find(creator_open)
|
||||
if open_tag_pos == -1:
|
||||
creator_close_to_find = "<dc:" + name + "/>"
|
||||
else:
|
||||
creator_close_to_find = "</dc:" + name + ">"
|
||||
close_tag_pos = data.find(creator_close_to_find)
|
||||
last_tag_pos = data.find("</cp:coreProperties>")
|
||||
|
||||
if open_tag_pos != -1 and close_tag_pos != - 1:
|
||||
data = data[:open_tag_pos + len(creator_open)] + value + data[close_tag_pos:]
|
||||
elif close_tag_pos != - 1:
|
||||
data = data[:close_tag_pos] + creator_open + value + creator_close + data[close_tag_pos + len(creator_close_to_find):]
|
||||
else:
|
||||
data = data[:last_tag_pos] + creator_open + value + creator_close + data[last_tag_pos:]
|
||||
return data
|
||||
|
||||
def change_author_name(file_input):
|
||||
temp_dir = os.getcwd().replace("\\", "/") + "/temp"
|
||||
base.create_dir(temp_dir)
|
||||
|
||||
app = "7za" if ("mac" == base.host_platform()) else "7z"
|
||||
base.cmd_exe(app, ["x", "-y", file_input, "-o" + temp_dir, "docProps/core.xml", "-r"])
|
||||
|
||||
with open(temp_dir + "/docProps/core.xml", 'r', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
|
||||
data = change_property(data, "creator", "")
|
||||
data = change_property(data, "lastModifiedBy", "")
|
||||
|
||||
with open(temp_dir + "/docProps/core.xml", 'w', encoding='utf-8') as file:
|
||||
file.write(data)
|
||||
|
||||
base.cmd_exe(app, ["a", "-r", file_input, temp_dir + "/docProps"])
|
||||
base.delete_dir(temp_dir)
|
||||
|
||||
def get_files(dir):
|
||||
arr_files = []
|
||||
for file in glob.glob(dir + "/*"):
|
||||
if base.is_file(file):
|
||||
arr_files.append(file)
|
||||
elif base.is_dir(file):
|
||||
arr_files += get_files(file)
|
||||
return arr_files
|
||||
|
||||
def get_local_path(base, src_dir):
|
||||
test1 = base.replace("\\", "/")
|
||||
test2 = src_dir.replace("\\", "/")
|
||||
return test2[len(test1)+1:]
|
||||
|
||||
params = sys.argv[1:]
|
||||
|
||||
if (3 > len(params)):
|
||||
print("use: convert.py path_to_x2t_directory path_to_input_directory path_to_output_directory")
|
||||
exit(0)
|
||||
|
||||
base.configure_common_apps()
|
||||
|
||||
x2t_directory = params[0]
|
||||
src_directory = params[1]
|
||||
dst_directory = params[2]
|
||||
|
||||
if base.is_dir(dst_directory):
|
||||
base.delete_dir(dst_directory)
|
||||
base.create_dir(dst_directory)
|
||||
|
||||
src_files = get_files(src_directory)
|
||||
|
||||
for file in src_files:
|
||||
directory = os.path.dirname(file)
|
||||
name = os.path.basename(file)
|
||||
directory_out_file = dst_directory + "/" + get_local_path(src_directory, directory)
|
||||
if not base.is_dir(directory_out_file):
|
||||
os.makedirs(directory_out_file, exist_ok=True)
|
||||
name_without_ext = os.path.splitext(name)[0]
|
||||
name_ext = os.path.splitext(name)[1][1:]
|
||||
|
||||
dst_ext = name_ext
|
||||
if ("docx" == name_ext) or ("dotx" == name_ext):
|
||||
dst_ext = "dotx"
|
||||
elif ("pptx" == name_ext) or ("potx" == name_ext):
|
||||
dst_ext = "potx"
|
||||
elif ("xlsx" == name_ext) or ("xltx" == name_ext):
|
||||
dst_ext = "xltx"
|
||||
|
||||
dst_name = name_without_ext
|
||||
if (len(dst_name) < 4) or (dst_name[0:4] != "[32]"):
|
||||
dst_name = "[32]" + base64.b32encode(name_without_ext.encode("utf-8")).decode("utf-8")
|
||||
|
||||
dst_file = directory_out_file + "/" + dst_name + "." + dst_ext
|
||||
|
||||
os.makedirs(directory_out_file, exist_ok=True)
|
||||
base.cmd_in_dir(x2t_directory, "x2t", [file, dst_file])
|
||||
|
||||
change_author_name(dst_file)
|
||||
|
||||
print(name_without_ext + " => " + dst_name)
|
||||
5
tools/linux/arm/cross_arm64/.gitignore
vendored
Normal file
5
tools/linux/arm/cross_arm64/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
qt_source*
|
||||
qt_binary*
|
||||
qt_build*
|
||||
qt-*
|
||||
gcc-linaro-*
|
||||
103
tools/linux/arm/cross_arm64/build_qt.py
Normal file
103
tools/linux/arm/cross_arm64/build_qt.py
Normal file
@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append('../../../../scripts')
|
||||
|
||||
import base
|
||||
|
||||
def update_qmake_conf(arm_toolchain_bin):
|
||||
replace_file = "./qt-everywhere-src-5.15.2/qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf"
|
||||
arm_toolchain_bin = os.path.abspath(arm_toolchain_bin)
|
||||
|
||||
replace_src = ""
|
||||
replace_src += "# modifications to g++.conf\n"
|
||||
replace_src += "QMAKE_CC = aarch64-linux-gnu-gcc\n"
|
||||
replace_src += "QMAKE_CXX = aarch64-linux-gnu-g++\n"
|
||||
replace_src += "QMAKE_LINK = aarch64-linux-gnu-g++\n"
|
||||
replace_src += "QMAKE_LINK_SHLIB = aarch64-linux-gnu-g++\n"
|
||||
replace_src += "\n"
|
||||
replace_src += "# modifications to linux.conf\n"
|
||||
replace_src += "QMAKE_AR = aarch64-linux-gnu-ar cqs\n"
|
||||
replace_src += "QMAKE_OBJCOPY = aarch64-linux-gnu-objcopy\n"
|
||||
replace_src += "QMAKE_NM = aarch64-linux-gnu-nm -P\n"
|
||||
replace_src += "QMAKE_STRIP = aarch64-linux-gnu-strip\n"
|
||||
|
||||
replace_dst = ""
|
||||
replace_dst += "# modifications to g++.conf\n"
|
||||
replace_dst += "QMAKE_CC = " + arm_toolchain_bin + "/aarch64-linux-gnu-gcc\n"
|
||||
replace_dst += "QMAKE_CXX = " + arm_toolchain_bin + "/aarch64-linux-gnu-g++\n"
|
||||
replace_dst += "QMAKE_LINK = " + arm_toolchain_bin + "/aarch64-linux-gnu-g++\n"
|
||||
replace_dst += "QMAKE_LINK_SHLIB = " + arm_toolchain_bin + "/aarch64-linux-gnu-g++\n"
|
||||
replace_dst += "\n"
|
||||
replace_dst += "# modifications to linux.conf\n"
|
||||
replace_dst += "QMAKE_AR = " + arm_toolchain_bin + "/aarch64-linux-gnu-ar cqs\n"
|
||||
replace_dst += "QMAKE_OBJCOPY = " + arm_toolchain_bin + "/aarch64-linux-gnu-objcopy\n"
|
||||
replace_dst += "QMAKE_NM = " + arm_toolchain_bin + "/aarch64-linux-gnu-nm -P\n"
|
||||
replace_dst += "QMAKE_STRIP = " + arm_toolchain_bin + "/aarch64-linux-gnu-strip\n"
|
||||
|
||||
base.replaceInFile(replace_file, replace_src, replace_dst)
|
||||
|
||||
def make(arm_toolchain_bin=""):
|
||||
qt_build_path = os.path.dirname(os.path.abspath(__file__)) + "/qt_build/Qt-5.15.2/linux_arm64"
|
||||
qt_params = ["-opensource",
|
||||
"-confirm-license",
|
||||
"-release",
|
||||
"-shared",
|
||||
"-accessibility",
|
||||
"-prefix", "\"" + qt_build_path + "\"",
|
||||
"-extprefix", "\"" + qt_build_path + "\"",
|
||||
"-hostprefix", "\"" + qt_build_path + "\"",
|
||||
"-c++std", "c++11",
|
||||
"-qt-zlib",
|
||||
"-qt-libpng",
|
||||
"-qt-libjpeg",
|
||||
"-qt-pcre",
|
||||
"-no-sql-sqlite",
|
||||
"-no-opengl",
|
||||
"-nomake", "examples",
|
||||
"-nomake", "tests",
|
||||
"-skip", "qtlocation",
|
||||
"-skip", "qtserialport",
|
||||
"-skip", "qtsensors",
|
||||
"-skip", "qtxmlpatterns",
|
||||
"-skip", "qt3d",
|
||||
"-skip", "qtwebview",
|
||||
"-skip", "qtwebengine",
|
||||
"-skip", "qtdeclarative",
|
||||
"-xplatform", "linux-aarch64-gnu-g++", # be sure that aarch64 gnu compiler is installed
|
||||
"-no-pch"]
|
||||
|
||||
qt_params_str = ""
|
||||
for param in qt_params:
|
||||
qt_params_str += (param + " ")
|
||||
|
||||
qt_url = "https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/qt/qt-everywhere-src-5.15.2.tar.xz"
|
||||
if not base.is_file("./qt_source_5.15.2.tar.xz"):
|
||||
base.download(qt_url, "./qt_source_5.15.2.tar.xz")
|
||||
|
||||
if not base.is_dir("./qt-everywhere-src-5.15.2"):
|
||||
base.cmd("tar", ["-xf", "./qt_source_5.15.2.tar.xz"])
|
||||
|
||||
# https://bugreports.qt.io/browse/QTBUG-93452
|
||||
# for GCC 11 and Qt5/Qt6
|
||||
additional_gcc_11 = "#ifdef __cplusplus\n#include <limits>\n#endif\n"
|
||||
chanage_file = "./qt-everywhere-src-5.15.2/qtbase/src/corelib/global/qglobal.h"
|
||||
filedata = base.readFile(chanage_file)
|
||||
if filedata.find(additional_gcc_11) == -1:
|
||||
filedata = additional_gcc_11 + filedata
|
||||
base.writeFile(chanage_file, filedata)
|
||||
|
||||
if arm_toolchain_bin != "":
|
||||
update_qmake_conf(arm_toolchain_bin)
|
||||
|
||||
base.cmd_in_dir("./qt-everywhere-src-5.15.2", "./configure " + qt_params_str)
|
||||
base.cmd_in_dir("./qt-everywhere-src-5.15.2", "make -j4")
|
||||
base.cmd_in_dir("./qt-everywhere-src-5.15.2", "make install")
|
||||
|
||||
if __name__ == "__main__":
|
||||
arm_toolchain_path = "./gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu/bin"
|
||||
if len(sys.argv) != 1:
|
||||
arm_toolchain_path = sys.argv[1]
|
||||
|
||||
make(arm_toolchain_path)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user