Compare commits

..

4 Commits

131 changed files with 2471 additions and 8707 deletions

View File

@ -1,24 +1,21 @@
name: Markdown Lint
name: Markdown check
on:
workflow_dispatch:
push:
branches:
- '**'
- '*'
paths:
- '*.md'
- 'develop/*.md'
- 'scripts/**.md'
- '.markdownlint.jsonc'
jobs:
markdownlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DavidAnson/markdownlint-cli2-action@v16
- uses: actions/checkout@v3
- uses: DavidAnson/markdownlint-cli2-action@v9
with:
globs: |
*.md
develop/*.md
scripts/**.md
globs: '*.md,develop/*.md,scripts/**.md'
separator: ','

View File

@ -1,88 +0,0 @@
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

View File

@ -3,13 +3,16 @@ name: Update hard-coded version
on: workflow_dispatch
jobs:
update-version:
if: >-
${{ contains(github.ref, 'refs/heads/hotfix/v') ||
contains(github.ref, 'refs/heads/release/v') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ secrets.PUSH_TOKEN }}
@ -22,9 +25,9 @@ jobs:
run: echo "${{ env.version }}" > version
- name: Commit & push changes
uses: EndBug/add-and-commit@v9
uses: EndBug/add-and-commit@v8
with:
author_name: github-actions[bot]
author_email: github-actions[bot]@users.noreply.github.com
message: Update hard-coded version to ${{ env.version }}
message: Update hard-coded version to v${{ env.version }}
add: version

2
.gitignore vendored
View File

@ -12,5 +12,3 @@ tests/puppeteer/node_modules
tests/puppeteer/work_directory
tests/puppeteer/package.json
tests/puppeteer/package-lock.json
scripts/sdkjs_common/jsdoc/node_modules
scripts/sdkjs_common/jsdoc/package-lock.json

View File

@ -1,5 +0,0 @@
{
"line-length": {
"code_block_line_length": 300
}
}

View File

@ -1,4 +1,4 @@
FROM ubuntu:20.04
FROM ubuntu:16.04
ENV TZ=Etc/UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
@ -11,4 +11,5 @@ RUN rm /usr/bin/python && ln -s /usr/bin/python2 /usr/bin/python
ADD . /build_tools
WORKDIR /build_tools
CMD ["sh", "-c", "cd tools/linux && python3 ./automate.py"]
CMD cd tools/linux && \
python3 ./automate.py

View File

@ -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
@ -196,8 +196,9 @@ LD_LIBRARY_PATH=./ ./DesktopEditors
**Note**: The created database must have **onlyoffice** both for user and password.
```bash
sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH PASSWORD 'onlyoffice';"
sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice OWNER onlyoffice;"
sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice;"
sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH password 'onlyoffice';"
sudo -i -u postgres psql -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;"
```
3. Configure the database:

132
build.pro Normal file
View File

@ -0,0 +1,132 @@
TEMPLATE = subdirs
ROOT_DIR=$$PWD/..
DEPLOY_DIR=$$PWD/deploy
CORE_ROOT_DIR=$$ROOT_DIR/core
include($$PWD/common.pri)
CONFIG += ordered
core_windows {
desktop:CONFIG += core_and_multimedia
}
core_linux {
desktop:CONFIG += core_and_multimedia
}
core_mac {
CONFIG += no_desktop_apps
}
core_ios {
CONFIG += no_use_common_binary
CONFIG += no_desktop_apps
CONFIG += no_tests
}
core_android {
CONFIG += no_use_common_binary
CONFIG += no_desktop_apps
CONFIG += no_tests
}
addSubProject(cryptopp, $$CORE_ROOT_DIR/Common/3dParty/cryptopp/project/cryptopp.pro)
addSubProject(cfcpp, $$CORE_ROOT_DIR/Common/cfcpp/cfcpp.pro)
addSubProject(unicodeconverter, $$CORE_ROOT_DIR/UnicodeConverter/UnicodeConverter.pro,\
cryptopp)
addSubProject(kernel, $$CORE_ROOT_DIR/Common/kernel.pro,\
unicodeconverter)
addSubProject(network, $$CORE_ROOT_DIR/Common/Network/network.pro,\
kernel unicodeconverter)
addSubProject(graphics, $$CORE_ROOT_DIR/DesktopEditor/graphics/pro/graphics.pro,\
kernel unicodeconverter)
addSubProject(pdffile, $$CORE_ROOT_DIR/PdfFile/PdfFile.pro,\
kernel unicodeconverter graphics)
addSubProject(djvufile, $$CORE_ROOT_DIR/DjVuFile/DjVuFile.pro,\
kernel unicodeconverter graphics pdffile)
addSubProject(xpsfile, $$CORE_ROOT_DIR/XpsFile/XpsFile.pro,\
kernel unicodeconverter graphics pdffile)
addSubProject(htmlrenderer, $$CORE_ROOT_DIR/HtmlRenderer/htmlrenderer.pro,\
kernel unicodeconverter graphics)
addSubProject(docxrenderer, $$CORE_ROOT_DIR/DocxRenderer/DocxRenderer.pro,\
kernel unicodeconverter graphics)
addSubProject(htmlfile2, $$CORE_ROOT_DIR/HtmlFile2/HtmlFile2.pro,\
kernel unicodeconverter graphics network)
addSubProject(doctrenderer, $$CORE_ROOT_DIR/DesktopEditor/doctrenderer/doctrenderer.pro,\
kernel unicodeconverter graphics)
addSubProject(fb2file, $$CORE_ROOT_DIR/Fb2File/Fb2File.pro,\
kernel unicodeconverter graphics)
addSubProject(epubfile, $$CORE_ROOT_DIR/EpubFile/CEpubFile.pro,\
kernel unicodeconverter graphics htmlfile2)
!no_x2t {
addSubProject(docxformat, $$CORE_ROOT_DIR/OOXML/Projects/Linux/DocxFormatLib/DocxFormatLib.pro)
addSubProject(pptxformat, $$CORE_ROOT_DIR/OOXML/Projects/Linux/PPTXFormatLib/PPTXFormatLib.pro)
addSubProject(xlsbformat, $$CORE_ROOT_DIR/OOXML/Projects/Linux/XlsbFormatLib/XlsbFormatLib.pro)
addSubProject(docformat, $$CORE_ROOT_DIR/MsBinaryFile/Projects/DocFormatLib/Linux/DocFormatLib.pro)
addSubProject(pptformat, $$CORE_ROOT_DIR/MsBinaryFile/Projects/PPTFormatLib/Linux/PPTFormatLib.pro)
addSubProject(xlsformat, $$CORE_ROOT_DIR/MsBinaryFile/Projects/XlsFormatLib/Linux/XlsFormatLib.pro)
addSubProject(vbaformat, $$CORE_ROOT_DIR/MsBinaryFile/Projects/VbaFormatLib/Linux/VbaFormatLib.pro)
addSubProject(txtxmlformat, $$CORE_ROOT_DIR/TxtFile/Projects/Linux/TxtXmlFormatLib.pro)
addSubProject(rtfformat, $$CORE_ROOT_DIR/RtfFile/Projects/Linux/RtfFormatLib.pro)
addSubProject(odffile, $$CORE_ROOT_DIR/OdfFile/Projects/Linux/OdfFormatLib.pro)
addSubProject(bindocument, $$CORE_ROOT_DIR/OOXML/Projects/Linux/BinDocument/BinDocument.pro)
addSubProject(x2t, $$CORE_ROOT_DIR/X2tConverter/build/Qt/X2tConverter.pro,\
docxformat pptxformat xlsbformat docformat pptformat xlsformat vbaformat txtxmlformat rtfformat odffile cfcpp bindocument fb2file epubfile docxrenderer)
}
!no_use_common_binary {
addSubProject(allfontsgen, $$CORE_ROOT_DIR/DesktopEditor/AllFontsGen/AllFontsGen.pro,\
kernel unicodeconverter graphics)
addSubProject(allthemesgen, $$CORE_ROOT_DIR/DesktopEditor/allthemesgen/allthemesgen.pro,\
kernel unicodeconverter graphics)
addSubProject(docbuilder, $$CORE_ROOT_DIR/DesktopEditor/doctrenderer/app_builder/docbuilder.pro,\
kernel unicodeconverter graphics doctrenderer)
addSubProject(pluginsmanager, $$CORE_ROOT_DIR/DesktopEditor/pluginsmanager/pluginsmanager.pro,\
kernel)
addSubProject(vboxtester, $$CORE_ROOT_DIR/DesktopEditor/vboxtester/vboxtester.pro,\
kernel)
}
!no_tests {
addSubProject(standardtester, $$CORE_ROOT_DIR/Test/Applications/StandardTester/standardtester.pro)
addSubProject(x2ttester, $$CORE_ROOT_DIR/Test/Applications/x2tTester/x2ttester.pro)
#TODO:
!linux_arm64:addSubProject(ooxml_crypt, $$CORE_ROOT_DIR/OfficeCryptReader/ooxml_crypt/ooxml_crypt.pro)
}
core_and_multimedia {
addSubProject(videoplayer, $$ROOT_DIR/desktop-sdk/ChromiumBasedEditors/videoplayerlib/videoplayerlib.pro,\
kernel unicodeconverter graphics)
}
desktop {
message(desktop)
addSubProject(hunspell, $$CORE_ROOT_DIR/Common/3dParty/hunspell/qt/hunspell.pro)
addSubProject(ooxmlsignature, $$CORE_ROOT_DIR/DesktopEditor/xmlsec/src/ooxmlsignature.pro,\
kernel unicodeconverter graphics)
addSubProject(documentscore, $$ROOT_DIR/desktop-sdk/ChromiumBasedEditors/lib/ascdocumentscore.pro,\
kernel unicodeconverter graphics hunspell ooxmlsignature htmlrenderer pdffile djvufile xpsfile)
addSubProject(documentscore_helper, $$ROOT_DIR/desktop-sdk/ChromiumBasedEditors/lib/ascdocumentscore_helper.pro,\
documentscore)
!core_mac {
addSubProject(qtdocumentscore, $$ROOT_DIR/desktop-sdk/ChromiumBasedEditors/lib/qt_wrapper/qtascdocumentscore.pro,\
documentscore)
}
!no_desktop_apps {
core_windows:addSubProject(projicons, $$ROOT_DIR/desktop-apps/win-linux/extras/projicons/ProjIcons.pro,\
documentscore videoplayer)
core_windows:!build_xp:addSubProject(updatedaemon, $$ROOT_DIR/desktop-apps/win-linux/extras/update-daemon/UpdateDaemon.pro)
addSubProject(desktopapp, $$ROOT_DIR/desktop-apps/win-linux/ASCDocumentEditor.pro,\
documentscore videoplayer)
}
}
mobile {
message(mobile)
!desktop {
addSubProject(hunspell, $$CORE_ROOT_DIR/Common/3dParty/hunspell/qt/hunspell.pro)
}
}

View File

@ -21,13 +21,12 @@ parser.add_option("--qt-dir-xp", action="store", type="string", dest="qt-dir-xp"
parser.add_option("--external-folder", action="store", type="string", dest="external-folder", default="", help="defines a directory with external folder")
parser.add_option("--sql-type", action="store", type="string", dest="sql-type", default="postgres", help="defines the sql type wich will be used")
parser.add_option("--db-port", action="store", type="string", dest="db-port", default="5432", help="defines the sql db-port wich will be used")
parser.add_option("--db-name", action="store", type="string", dest="db-name", default="onlyoffice", help="defines the sql db-name wich will be used")
parser.add_option("--db-user", action="store", type="string", dest="db-user", default="onlyoffice", help="defines the sql db-user wich will be used")
parser.add_option("--db-pass", action="store", type="string", dest="db-pass", default="onlyoffice", help="defines the sql db-pass wich will be used")
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="auto", 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="https", 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")

View File

@ -1,3 +1,3 @@
sdkjs-plugin="photoeditor, macros, ocr, translator, thesaurus, youtube, highlightcode, zotero"
sdkjs-plugin-server="speech, zotero, mendeley, speechrecognition, drawio"
sdkjs-plugin="photoeditor, macros, ocr, translator, thesaurus, youtube, highlightcode"
sdkjs-plugin-server="speech, zotero, mendeley"
sdkjs-addons="sdkjs-forms"

View File

@ -3,17 +3,11 @@ RUN apt-get update -y && \
apt-get install git -y \
python3 -y \
openjdk-11-jdk -y \
bzip2 -y \
npm -y && \
npm install -g grunt grunt-cli -y && \
npm install -g grunt-cli -y && \
ln -s /usr/bin/python3 /usr/bin/python && \
ln -s /usr/bin/pip3 /usr/bin/pip && \
git clone --depth 1 https://github.com/ONLYOFFICE/build_tools.git var/www/onlyoffice/documentserver/build_tools && \
sed -i '/documentserver-static-gzip.sh ${ONLYOFFICE_DATA_CONTAINER}/d' /app/ds/run-document-server.sh && \
#Set Up Debug Logging
sed -i 's/WARN/ALL/g' /etc/onlyoffice/documentserver/log4js/production.json && \
#Start test example
if [ -s /etc/supervisor/conf.d/ds-example.conf ] ; then sed -i 's,autostart=false,autostart=true,' /etc/supervisor/conf.d/ds-example.conf; fi && \
if [ -s /app/ds/setup/config/supervisor/ds/ds-example.conf ] ; then sed -i 's,autostart=false,autostart=true,' /app/ds/setup/config/supervisor/ds/ds-example.conf; fi && \
rm -rf /var/lib/apt/lists/*
ENTRYPOINT python3 /var/www/onlyoffice/documentserver/build_tools/develop/run_build_js.py /var/www/onlyoffice/documentserver $@ && /bin/sh -c /app/ds/run-document-server.sh
ENTRYPOINT python3 /var/www/onlyoffice/documentserver/build_tools/develop/run_build_js.py /var/www/onlyoffice/documentserver && /bin/sh -c /app/ds/run-document-server.sh

View File

@ -1,223 +1,50 @@
# Docker
This directory containing instruction for developers,
who want to change something in sdkjs or web-apps or server module,
who want to change something in sdkjs or web-apps module,
but don't want to compile pretty compilcated core product to make those changes.
## System requirements
## Installing ONLYOFFICE Docs
**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.
## How to use - Linux or macOS
### Windows
**Note**: You need the latest Docker version installed.
You need the latest
[Docker Desktop for Windows](https://docs.docker.com/desktop/install/windows-install/)
installed.
**Note**: Docker Desktop does not start automatically after installation.
You should manually start the **Docker Desktop** application.
**Note**: If you have problems running Docker Desktop with the
"Use WSL 2 instead of Hyper-V" installation option,
try reinstalling it without this option.
### Linux or macOS
You need the latest
[Docker](https://docs.docker.com/engine/install/)
version installed.
## Create develop Docker Images
To create a image with the ability to include external non-minified sdkjs code,
use the following commands:
### Clone development environment to work dir
```bash
git clone https://github.com/ONLYOFFICE/build_tools.git
```
### Modify Docker Images
You might need to pull **onlyoffice/documentserver** image:
**Note**: Do not prefix docker command with sudo.
[This](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)
instruction show how to use docker without sudo.
```bash
cd build_tools/develop
docker pull onlyoffice/documentserver
docker build --no-cache -t documentserver-develop .
```
### Create develop image
To create a image with the ability to include external non-minified sdkjs code,
use the following command:
```bash
git clone https://github.com/ONLYOFFICE/build_tools.git
cd build_tools/develop
docker build -t documentserver-develop .
```
**Note**: The dot at the end is required.
**Note**: Sometimes script may fail due to network errors. Just restart it.
### Connecting external folders
## Clone development modules
Clone development modules to the work dir
To connect external folders to the container,
you need to pass the "-v" parameter
along with the relative paths to the required folders.
The folders `sdkjs` and `web-apps` are required for proper development workflow
* `sdkjs` repo is located [here](https://github.com/ONLYOFFICE/sdkjs/)
* `web-apps` repo is located [here](https://github.com/ONLYOFFICE/web-apps/)
* `server` repo is located [here](https://github.com/ONLYOFFICE/server/)
```bash
git clone https://github.com/ONLYOFFICE/sdkjs.git
git clone https://github.com/ONLYOFFICE/web-apps.git
git clone https://github.com/ONLYOFFICE/server.git
```
## Start server with external folders
To mount external folders to the container,
you need to pass the "-v" parameter
along with the relative paths to the required folders.
The folders `sdkjs` and `web-apps` are required for proper development workflow.
The folders `server` is optional
**Note**: Run command with the current working directory
containing `sdkjs`, `web-apps`...
**Note**: ONLYOFFICE server uses port 80.
Look for another application using port 80 and stop it
**Note**: Server start with `sdkjs` and `web-apps` takes 15 minutes
and takes 20 minutes with `server`
### docker run on Windows (PowerShell)
**Note**: Run PowerShell as administrator to fix EACCES error when installing
node_modules
run with `sdkjs` and `web-apps`
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true -v $pwd/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $pwd/web-apps:/var/www/onlyoffice/documentserver/web-apps documentserver-develop
```
or run with `sdkjs`, `web-apps` and `server`
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true -v $pwd/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $pwd/web-apps:/var/www/onlyoffice/documentserver/web-apps -v $pwd/server:/var/www/onlyoffice/documentserver/server documentserver-develop
```
### docker run on Linux or macOS
run with `sdkjs` and `web-apps`
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true -v $(pwd)/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $(pwd)/web-apps:/var/www/onlyoffice/documentserver/web-apps documentserver-develop
```
or run with `sdkjs`, `web-apps` and `server`
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true -v $(pwd)/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $(pwd)/web-apps:/var/www/onlyoffice/documentserver/web-apps -v $(pwd)/server:/var/www/onlyoffice/documentserver/server documentserver-develop
```
## Open editor
After the server starts successfully, you will see Docker log messages like this
```bash
[Date] [WARN] [localhost] [docId] [userId] nodeJS
```
To try the document editor, open a browser tab and type
[http://localhost/example](http://localhost/example) into the URL bar.
**Note**: Disable **ad blockers** for localhost page.
It may block some scripts (like Analytics.js)
## Modify sources
### To change something in `sdkjs` do the following steps
1)Edit source file. Let's insert an image url into each open document.
Following command inserts (in case of problems, you can replace URL)
`this.AddImageUrl(['http://localhost/example/images/logo.png']);`
after event
`this.sendEvent('asc_onDocumentContentReady');`
in file
`sdkjs/common/apiBase.js`
### change sdkjs on Windows (PowerShell)
```bash
(Get-Content sdkjs/common/apiBase.js) -replace "this\.sendEvent\('asc_onDocumentContentReady'\);", "this.sendEvent('asc_onDocumentContentReady');this.AddImageUrl(['http://localhost/example/images/logo.png']);" | Set-Content sdkjs/common/apiBase.js
```
### change sdkjs on Linux or macOS
```bash
sed -i "s,this.sendEvent('asc_onDocumentContentReady');,this.sendEvent('asc_onDocumentContentReady');this.AddImageUrl(['http://localhost/example/images/logo.png']);," sdkjs/common/apiBase.js
```
2)Delete browser cache or hard reload the page `Ctrl + Shift + R`
3)Open new file in browser
### To change something in `server` do the following steps
1)Edit source file. Let's send `"Hello World!"`
chart message every time a document is opened.
Following command inserts
`yield* onMessage(ctx, conn, {"message": "Hello World!"});`
in function
`sendAuthInfo`
in file
`server/DocService/sources/DocsCoServer.js`
### change server on Windows (PowerShell)
```bash
(Get-Content server/DocService/sources/DocsCoServer.js) -replace 'opt_hasForgotten, opt_openedAt\) \{', 'opt_hasForgotten, opt_openedAt) {yield* onMessage(ctx, conn, {"message": "Hello World!"});' | Set-Content server/DocService/sources/DocsCoServer.js
```
### change server on Linux or macOS
```bash
sed -i 's#opt_hasForgotten, opt_openedAt) {#opt_hasForgotten, opt_openedAt) {yield* onMessage(ctx, conn, {"message": "Hello World!"});#' server/DocService/sources/DocsCoServer.js
```
2)Restart document server process
**Note**: Look for ``CONTAINER_ID`` in the result of ``docker ps``.
```bash
docker exec -it CONTAINER_ID supervisorctl restart all
```
3)Open new file in browser
## Start server with additional functionality(addons)
To get additional functionality and branding you need to connect a branding folder,
additional addon folders and pass command line arguments
For example run with `onlyoffice` branding and
addons:`sdkjs-forms`, `sdkjs-ooxml`, `web-apps-mobile`
### docker run on Windows (PowerShell) with branding
**Note**: Run PowerShell as administrator to fix EACCES error when installing
node_modules
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true `
-v $pwd/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $pwd/web-apps:/var/www/onlyoffice/documentserver/web-apps `
-v $pwd/onlyoffice:/var/www/onlyoffice/documentserver/onlyoffice -v $pwd/sdkjs-ooxml:/var/www/onlyoffice/documentserver/sdkjs-ooxml -v $pwd/sdkjs-forms:/var/www/onlyoffice/documentserver/sdkjs-forms -v $pwd/web-apps-mobile:/var/www/onlyoffice/documentserver/web-apps-mobile `
documentserver-develop args --branding onlyoffice --branding-url 'https://github.com/ONLYOFFICE/onlyoffice.git' --siteUrl localhost
```
### docker run on Linux or macOS with branding
```bash
docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true \
-v $(pwd)/sdkjs:/var/www/onlyoffice/documentserver/sdkjs -v $(pwd)/web-apps:/var/www/onlyoffice/documentserver/web-apps \
-v $(pwd)/onlyoffice:/var/www/onlyoffice/documentserver/onlyoffice -v $(pwd)/sdkjs-ooxml:/var/www/onlyoffice/documentserver/sdkjs-ooxml -v $(pwd)/sdkjs-forms:/var/www/onlyoffice/documentserver/sdkjs-forms -v $(pwd)/web-apps-mobile:/var/www/onlyoffice/documentserver/web-apps-mobile \
documentserver-develop args --branding onlyoffice --branding-url 'https://github.com/ONLYOFFICE/onlyoffice.git' --siteUrl localhost
docker run -i -t -d -p 80:80 --restart=always \
-v /host-dir/sdkjs:/var/www/onlyoffice/documentserver/sdkjs \
-v /host-dir/web-apps:/var/www/onlyoffice/documentserver/web-apps documentserver-develop
```

View File

@ -2,56 +2,11 @@
import sys
sys.path.append(sys.argv[1] + '/build_tools/scripts')
sys.path.append(sys.argv[1] + '/build_tools/scripts/develop')
import build_js
import run_server
import config
import base
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:])
base.cmd_in_dir(sys.argv[1] + '/build_tools/', 'python3', ['configure.py'])
config.parse()
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")
# external server volume
if base.is_exist(sys.argv[1] + '/server/DocService/package.json'):
base.print_info('replace supervisor cfg to run docservice and converter from source')
base.replaceInFileRE("/etc/supervisor/conf.d/ds-docservice.conf", "command=.*", "command=node " + git_dir + "/server/DocService/sources/server.js")
base.replaceInFileRE("/app/ds/setup/config/supervisor/ds/ds-docservice.conf", "command=.*", "command=node " + git_dir + "/server/DocService/sources/server.js")
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()
else:
#Fix theme generation for external sdkjs volume
if base.is_exist(git_dir + "/server/FileConverter/bin/DoctRenderer.config"):
base.print_info('replace DoctRenderer.config for external sdkjs volume')
base.generate_doctrenderer_config(git_dir + "/server/FileConverter/bin/DoctRenderer.config", "../../../sdkjs/deploy/", "server", "../../../web-apps/vendor/", "../../../dictionaries")
addons = {}
addons.update(base.get_sdkjs_addons())
addons.update(base.get_web_apps_addons())
staticContent = ""
for addon in addons:
if (addon):
staticContent += '"/' + addon + '": {"path": "/var/www/onlyoffice/documentserver/' + addon + '","options": {"maxAge": "7d"}},'
if staticContent:
base.print_info('replace production-linux.json for addons'+staticContent)
base.replaceInFileRE("/etc/onlyoffice/documentserver/production-linux.json", '"static_content": {.*', '"static_content": {' + staticContent)
base.print_info('replace supervisor cfg to run docservice and converter from pkg')
base.replaceInFileRE("/etc/supervisor/conf.d/ds-docservice.conf", "command=node .*", "command=/var/www/onlyoffice/documentserver/server/DocService/docservice")
base.replaceInFileRE("/app/ds/setup/config/supervisor/ds/ds-docservice.conf", "command=node .*", "command=/var/www/onlyoffice/documentserver/server/DocService/docservice")
base.replaceInFileRE("/etc/supervisor/conf.d/ds-converter.conf", "command=node .*", "command=/var/www/onlyoffice/documentserver/server/FileConverter/converter")
base.replaceInFileRE("/app/ds/setup/config/supervisor/ds/ds-converter.conf", "command=node .*", "command=/var/www/onlyoffice/documentserver/server/FileConverter/converter")
base.print_info('run_server.run_docker_sdk_web_apps: ' + git_dir)
run_server.run_docker_sdk_web_apps(git_dir)
build_js.build_js_develop(sys.argv[1])

38
make.py
View File

@ -1,32 +1,19 @@
#!/usr/bin/env python
import os
import sys
__dir__name__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(__dir__name__ + '/scripts')
sys.path.append(__dir__name__ + '/scripts/develop')
sys.path.append(__dir__name__ + '/scripts/develop/vendor')
sys.path.append(__dir__name__ + '/scripts/core_common')
sys.path.append(__dir__name__ + '/scripts/core_common/modules')
sys.path.append(__dir__name__ + '/scripts/core_common/modules/android')
sys.path.append('scripts')
sys.path.append('scripts/develop')
sys.path.append('scripts/develop/vendor')
sys.path.append('scripts/core_common')
sys.path.append('scripts/core_common/modules')
import config
import base
import build_sln
import build
import build_js
import build_server
import deploy
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()
if (args.build_only_branding):
base.set_env("OO_BUILD_ONLY_BRANDING", "1")
# parse configuration
config.parse()
@ -72,31 +59,30 @@ if ("1" == config.option("update")):
base.configure_common_apps()
# developing...
develop.make()
develop.make();
# check only js builds
if ("1" == base.get_env("OO_ONLY_BUILD_JS")):
build_js.make()
exit(0)
#base.check_tools()
# core 3rdParty
make_common.make()
# build updmodule for desktop (only for windows version)
if config.check_option("module", "desktop"):
config.extend_option("qmake_addon", "URL_WEBAPPS_HELP=https://download.onlyoffice.com/install/desktop/editors/help/v" + base.get_env('PRODUCT_VERSION') + "/apps")
config.extend_option("qmake_addon", "URL_WEBAPPS_HELP=https://download.onlyoffice.com/install/desktop/editors/help/v" + base.get_env('PRODUCT_VERSION') + "-1/apps")
if "windows" == base.host_platform():
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>")
if ("windows" == base.host_platform()):
base.set_env("VIDEO_PLAYER_VLC_DIR", base_dir + "/../desktop-sdk/ChromiumBasedEditors/videoplayerlib/vlc")
# build
build_sln.make()
build.make()
# js
build_js.make()

View File

@ -10,20 +10,19 @@ 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("-V", "--version", dest="version", type=str,
action="store", help="Defines version")
parser.add_argument("-B", "--build", dest="build", type=str,
action="store", help="Defines build")
parser.add_argument("-H", "--branch", dest="branch", type=str,
action="store", help="Defines branch")
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="Provides branding path")
parser.add_argument("-V", "--version", dest="version", type=str,
action="store", help="Defines version")
parser.add_argument("-B", "--build", dest="build", type=str,
action="store", help="Defines build")
args = parser.parse_args()
# vars
common.workspace_dir = utils.get_abspath(utils.get_script_dir(__file__) + "/..")
common.os_family = utils.host_platform()
common.platform = args.platform
common.prefix = common.platformPrefixes[common.platform] if common.platform in common.platformPrefixes else ""
@ -31,21 +30,14 @@ common.targets = args.targets
common.clean = "clean" in args.targets
common.sign = "sign" in args.targets
common.deploy = "deploy" in args.targets
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.version = args.version if (args.version is not None) else utils.get_env("PRODUCT_VERSION", "1.0.0")
common.build = args.build if (args.build is not None) else utils.get_env("BUILD_NUMBER", "1")
common.channel = utils.get_env("BUILD_CHANNEL", "other")
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.summary = []
common.deploy_data = []
utils.log("workspace_dir: " + common.workspace_dir)
utils.log("os_family: " + common.os_family)
utils.log("platform: " + str(common.platform))
utils.log("prefix: " + str(common.prefix))
@ -57,8 +49,6 @@ utils.log("version: " + common.version)
utils.log("build: " + common.build)
utils.log("branding: " + str(common.branding))
utils.log("timestamp: " + common.timestamp)
utils.log("workspace_dir: " + common.workspace_dir)
utils.log("branding_dir: " + common.branding_dir)
# branding
if common.branding is not None:
@ -73,26 +63,23 @@ import package_mobile
# build
utils.set_cwd(common.workspace_dir, verbose=True)
utils.delete_file("deploy.json")
if "core" in common.targets:
package_core.make()
if "closuremaps_sdkjs_opensource" in common.targets:
package_core.deploy_closuremaps_sdkjs("opensource")
if "closuremaps_sdkjs_commercial" in common.targets:
package_core.deploy_closuremaps_sdkjs("commercial")
if "closuremaps_webapps" in common.targets:
package_core.deploy_closuremaps_webapps("opensource")
if "closure-maps-os" in common.targets:
package_core.deploy_closure_maps("opensource")
if "closure-maps-com" in common.targets:
package_core.deploy_closure_maps("commercial")
if "desktop" in common.targets:
package_desktop.make()
if "builder" in common.targets:
package_builder.make()
if "server_community" in common.targets:
if "server-community" in common.targets:
package_server.make("community")
if "server_enterprise" in common.targets:
if "server-enterprise" in common.targets:
package_server.make("enterprise")
if "server_developer" in common.targets:
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()

File diff suppressed because it is too large Load Diff

118
scripts/build.py Normal file
View File

@ -0,0 +1,118 @@
#!/usr/bin/env python
import config
import base
import os
import multiprocessing
def make_pro_file(makefiles_dir, pro_file, qmake_config_addon=""):
platforms = config.option("platform").split()
for platform in platforms:
if not platform in config.platforms:
continue
print("------------------------------------------")
print("BUILD_PLATFORM: " + platform)
print("------------------------------------------")
old_env = dict(os.environ)
# if you need change output libraries path - set the env variable
# base.set_env("DESTDIR_BUILD_OVERRIDE", os.getcwd() + "/out/android/" + config.branding() + "/mobile")
isAndroid = False if (-1 == platform.find("android")) else True
if isAndroid:
toolchain_platform = "linux-x86_64"
if ("mac" == base.host_platform()):
toolchain_platform = "darwin-x86_64"
base.set_env("ANDROID_NDK_HOST", toolchain_platform)
old_path = base.get_env("PATH")
new_path = base.qt_setup(platform) + "/bin:"
new_path += (base.get_env("ANDROID_NDK_ROOT") + "/toolchains/llvm/prebuilt/" + toolchain_platform + "/bin:")
new_path += old_path
base.set_env("PATH", new_path)
base.set_env("ANDROID_NDK_PLATFORM", "android-21")
if (-1 != platform.find("ios")):
base.hack_xcode_ios()
# makefile suffix
file_suff = platform
if (config.check_option("config", "debug")):
file_suff += "_debug_"
file_suff += config.option("branding")
# setup qt
qt_dir = base.qt_setup(platform)
base.set_env("OS_DEPLOY", platform)
# qmake CONFIG+=...
config_param = base.qt_config(platform)
if ("" != qmake_config_addon):
config_param += (" " + qmake_config_addon)
# qmake ADDON
qmake_addon = []
if ("" != config.option("qmake_addon")):
qmake_addon = config.option("qmake_addon").split()
if not base.is_file(qt_dir + "/bin/qmake") and not base.is_file(qt_dir + "/bin/qmake.exe"):
print("THIS PLATFORM IS NOT SUPPORTED")
continue
# non windows platform
if not base.is_windows():
if base.is_file(makefiles_dir + "/build.makefile_" + file_suff):
base.delete_file(makefiles_dir + "/build.makefile_" + file_suff)
print("make file: " + makefiles_dir + "/build.makefile_" + file_suff)
base.cmd(qt_dir + "/bin/qmake", ["-nocache", pro_file, "CONFIG+=" + config_param] + qmake_addon)
if ("1" == config.option("clean")):
base.cmd_and_return_cwd(base.app_make(), ["clean", "-f", makefiles_dir + "/build.makefile_" + file_suff], True)
base.cmd_and_return_cwd(base.app_make(), ["distclean", "-f", makefiles_dir + "/build.makefile_" + file_suff], True)
base.cmd(qt_dir + "/bin/qmake", ["-nocache", pro_file, "CONFIG+=" + config_param] + qmake_addon)
if not base.is_file(pro_file):
base.cmd(qt_dir + "/bin/qmake", ["-nocache", pro_file, "CONFIG+=" + config_param] + qmake_addon)
if ("0" != config.option("multiprocess")):
base.cmd_and_return_cwd(base.app_make(), ["-f", makefiles_dir + "/build.makefile_" + file_suff, "-j" + str(multiprocessing.cpu_count())])
else:
base.cmd_and_return_cwd(base.app_make(), ["-f", makefiles_dir + "/build.makefile_" + file_suff])
else:
qmake_bat = []
qmake_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + ("x86" if base.platform_is_32(platform) else "x64"))
qmake_bat.append("if exist ./" + makefiles_dir + "/build.makefile_" + file_suff + " del /F ./" + makefiles_dir + "/build.makefile_" + file_suff)
qmake_addon_string = ""
if ("" != config.option("qmake_addon")):
qmake_addon_string = " " + (" ").join(["\"" + addon + "\"" for addon in qmake_addon])
qmake_bat.append("call \"" + qt_dir + "/bin/qmake\" -nocache " + pro_file + " \"CONFIG+=" + config_param + "\"" + qmake_addon_string)
if ("1" == config.option("clean")):
qmake_bat.append("call nmake clean -f " + makefiles_dir + "/build.makefile_" + file_suff)
qmake_bat.append("call nmake distclean -f " + makefiles_dir + "/build.makefile_" + file_suff)
qmake_bat.append("call \"" + qt_dir + "/bin/qmake\" -nocache " + pro_file + " \"CONFIG+=" + config_param + "\"" + qmake_addon_string)
if ("0" != config.option("multiprocess")):
qmake_bat.append("set CL=/MP")
qmake_bat.append("call nmake -f " + makefiles_dir + "/build.makefile_" + file_suff)
base.run_as_bat(qmake_bat)
os.environ.clear()
os.environ.update(old_env)
base.delete_file(".qmake.stash")
# make build.pro
def make():
make_pro_file("makefiles", "build.pro")
if config.check_option("platform", "ios") and config.check_option("config", "bundle_xcframeworks"):
make_pro_file("makefiles", "build.pro", "xcframework_platform_ios_simulator")
if config.check_option("module", "builder") and base.is_windows() and "onlyoffice" == config.branding():
# 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)
return

View File

@ -27,92 +27,89 @@ def correct_sdkjs_licence(directory):
def make():
if ("1" == base.get_env("OO_NO_BUILD_JS")):
return
if not base.is_need_build_js():
return
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
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")
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") and not isOnlyMobile:
if config.check_option("module", "desktop"):
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")
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]
# for bug 62528. remove empty folders
walklist = list(os.walk(out_dir + "/desktop/sdkjs"))
[os.remove(p) for p, _, _ in walklist[::-1] if len(os.listdir(p)) == 0]
if not base.is_file(out_dir + "/desktop/sdkjs/common/AllFonts.js"):
base.copy_file(base_dir + "/../sdkjs/common/HtmlFileInternal/AllFonts.js", out_dir + "/desktop/sdkjs/common/AllFonts.js")
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")
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")
base.copy_file(base_dir + "/../desktop-apps/common/loginpage/deploy/index.html", out_dir + "/desktop/index.html")
base.copy_file(base_dir + "/../desktop-apps/common/loginpage/deploy/noconnect.html", out_dir + "/desktop/noconnect.html")
# mobile
if config.check_option("module", "mobile"):
build_sdk_native(base_dir + "/../sdkjs/build")
build_sdk_native(base_dir + "/../sdkjs/build", False)
base.create_dir(out_dir + "/mobile")
base.create_dir(out_dir + "/mobile/sdkjs")
vendor_dir_src = base_dir + "/../web-apps/vendor/"
sdk_dir_src = base_dir + "/../sdkjs/deploy/sdkjs/"
prefix_js = [
vendor_dir_src + "xregexp/xregexp-all-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs-native/common/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"
]
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/common/Native/Wrappers/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/mobile/sdkjs/banners_word.js")
postfix_js = [
base_dir + "/../sdkjs/common/libfont/engine/fonts_native.js",
base_dir + "/../sdkjs/common/Charts/ChartStyles.js"
]
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/cell/native/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/mobile/sdkjs/banners_cell.js")
base.join_scripts(prefix_js, out_dir + "/mobile/sdkjs/banners.js")
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/common/Native/Wrappers/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/mobile/sdkjs/banners_slide.js")
base.create_dir(out_dir + "/mobile/sdkjs/word")
base.join_scripts([out_dir + "/mobile/sdkjs/banners.js", sdk_dir_src + "word/sdk-all-min.js", sdk_dir_src + "word/sdk-all.js"] + postfix_js, out_dir + "/mobile/sdkjs/word/script.bin")
base.join_scripts([out_dir + "/mobile/sdkjs/banners_word.js", sdk_dir_src + "word/sdk-all-min.js", sdk_dir_src + "word/sdk-all.js"], out_dir + "/mobile/sdkjs/word/script.bin")
base.create_dir(out_dir + "/mobile/sdkjs/cell")
base.join_scripts([out_dir + "/mobile/sdkjs/banners.js", sdk_dir_src + "cell/sdk-all-min.js", sdk_dir_src + "cell/sdk-all.js"] + postfix_js, out_dir + "/mobile/sdkjs/cell/script.bin")
base.join_scripts([out_dir + "/mobile/sdkjs/banners_cell.js", sdk_dir_src + "cell/sdk-all-min.js", sdk_dir_src + "cell/sdk-all.js"], out_dir + "/mobile/sdkjs/cell/script.bin")
base.create_dir(out_dir + "/mobile/sdkjs/slide")
base.join_scripts([out_dir + "/mobile/sdkjs/banners.js", sdk_dir_src + "slide/sdk-all-min.js", sdk_dir_src + "slide/sdk-all.js"] + postfix_js, out_dir + "/mobile/sdkjs/slide/script.bin")
base.join_scripts([out_dir + "/mobile/sdkjs/banners_slide.js", sdk_dir_src + "slide/sdk-all-min.js", sdk_dir_src + "slide/sdk-all.js"], out_dir + "/mobile/sdkjs/slide/script.bin")
base.delete_file(out_dir + "/mobile/sdkjs/banners.js")
base.delete_file(out_dir + "/mobile/sdkjs/banners_word.js")
base.delete_file(out_dir + "/mobile/sdkjs/banners_cell.js")
base.delete_file(out_dir + "/mobile/sdkjs/banners_slide.js")
return
# JS build
def _run_npm(directory):
retValue = base.cmd_in_dir(directory, "npm", ["install"], True)
if (0 != retValue):
retValue = base.cmd_in_dir(directory, "npm", ["install", "--verbose"])
return retValue
return base.cmd_in_dir(directory, "npm", ["install"])
def _run_npm_ci(directory):
return base.cmd_in_dir(directory, "npm", ["ci"])
@ -125,7 +122,7 @@ def _run_grunt(directory, params=[]):
def build_interface(directory):
_run_npm(directory)
_run_grunt(directory, ["--force", "--verbose"] + base.web_apps_addons_param())
_run_grunt(directory, ["--force"] + base.web_apps_addons_param())
return
def get_build_param(minimize=True):
@ -151,41 +148,27 @@ def build_sdk_builder(directory):
def build_sdk_native(directory, minimize=True):
#_run_npm_cli(directory)
_run_npm(directory)
addons = base.sdkjs_addons_param()
if not config.check_option("sdkjs-addons", "sdkjs-native"):
addons.append("--addon=sdkjs-native")
_run_grunt(directory, get_build_param(minimize) + ["--mobile=true"] + addons)
_run_grunt(directory, get_build_param(minimize) + ["--mobile=true"] + base.sdkjs_addons_param())
return
def build_sdkjs_develop(root_dir):
external_folder = config.option("--external-folder")
if (external_folder != ""):
external_folder = "/" + external_folder
_run_npm_ci(root_dir + external_folder + "/sdkjs/build")
_run_grunt(root_dir + external_folder + "/sdkjs/build", get_build_param(False) + base.sdkjs_addons_param())
_run_grunt(root_dir + external_folder + "/sdkjs/build", ["develop"] + base.sdkjs_addons_param())
def build_js_develop(root_dir):
#_run_npm_cli(root_dir + "/sdkjs/build")
external_folder = config.option("--external-folder")
if (external_folder != ""):
external_folder = "/" + external_folder
build_sdkjs_develop(root_dir)
_run_npm_ci(root_dir + external_folder + "/sdkjs/build")
_run_grunt(root_dir + external_folder + "/sdkjs/build", get_build_param(False) + base.sdkjs_addons_param())
_run_grunt(root_dir + external_folder + "/sdkjs/build", ["develop"] + base.sdkjs_addons_param())
_run_npm(root_dir + external_folder + "/web-apps/build")
_run_npm_ci(root_dir + external_folder + "/web-apps/build/sprites")
_run_npm(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")
base.set_env("PRODUCT_VERSION", old_product_version + "d")
os.chdir(root_dir + external_folder + "/web-apps/vendor/framework7-react")
base.cmd("npm", ["ci"])
base.cmd("npm", ["install"])
base.cmd("npm", ["run", "deploy-word"])
base.cmd("npm", ["run", "deploy-cell"])
base.cmd("npm", ["run", "deploy-slide"])

View File

@ -14,9 +14,6 @@ parser.add_option("--output",
parser.add_option("--write-version",
action="store_true", dest="write_version", default=False,
help="Create version file of build")
parser.add_option("--minimize",
action="store", type="string", dest="minimize", default="0",
help="Is minimized version")
(options, args) = parser.parse_args(arguments)
def write_version_files(output_dir):
@ -35,11 +32,7 @@ def write_version_files(output_dir):
# parse configuration
config.parse()
config.parse_defaults()
isMinimize = False
if ("1" == options.minimize or "true" == options.minimize):
isMinimize = True
config.set_option("jsminimize", "disable")
config.extend_option("jsminimize", "0")
branding = config.option("branding-name")
if ("" == branding):
@ -53,32 +46,41 @@ if (options.output):
base.create_dir(out_dir)
build_js.build_sdk_native(base_dir + "/../sdkjs/build", isMinimize)
build_js.build_sdk_native(base_dir + "/../sdkjs/build")
vendor_dir_src = base_dir + "/../web-apps/vendor/"
sdk_dir_src = base_dir + "/../sdkjs/deploy/sdkjs/"
prefix_js = [
vendor_dir_src + "xregexp/xregexp-all-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs-native/common/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"
]
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/common/Native/Wrappers/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/banners_word.js")
postfix_js = [
base_dir + "/../sdkjs/common/libfont/engine/fonts_native.js",
base_dir + "/../sdkjs/common/Charts/ChartStyles.js"
]
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/cell/native/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/banners_cell.js")
base.join_scripts(prefix_js, out_dir + "/banners.js")
base.join_scripts([vendor_dir_src + "xregexp/xregexp-all-min.js",
vendor_dir_src + "underscore/underscore-min.js",
base_dir + "/../sdkjs/common/Native/native.js",
base_dir + "/../sdkjs/common/Native/Wrappers/common.js",
base_dir + "/../sdkjs/common/Native/jquery_native.js"],
out_dir + "/banners_slide.js")
base.create_dir(out_dir + "/word")
base.join_scripts([out_dir + "/banners.js", sdk_dir_src + "word/sdk-all-min.js", sdk_dir_src + "word/sdk-all.js"] + postfix_js, out_dir + "/word/script.bin")
base.join_scripts([out_dir + "/banners_word.js", sdk_dir_src + "word/sdk-all-min.js", sdk_dir_src + "word/sdk-all.js"], out_dir + "/word/script.bin")
base.create_dir(out_dir + "/cell")
base.join_scripts([out_dir + "/banners.js", sdk_dir_src + "cell/sdk-all-min.js", sdk_dir_src + "cell/sdk-all.js"] + postfix_js, out_dir + "/cell/script.bin")
base.join_scripts([out_dir + "/banners_cell.js", sdk_dir_src + "cell/sdk-all-min.js", sdk_dir_src + "cell/sdk-all.js"], out_dir + "/cell/script.bin")
base.create_dir(out_dir + "/slide")
base.join_scripts([out_dir + "/banners.js", sdk_dir_src + "slide/sdk-all-min.js", sdk_dir_src + "slide/sdk-all.js"] + postfix_js, out_dir + "/slide/script.bin")
base.join_scripts([out_dir + "/banners_slide.js", sdk_dir_src + "slide/sdk-all-min.js", sdk_dir_src + "slide/sdk-all.js"], out_dir + "/slide/script.bin")
base.delete_file(out_dir + "/banners.js")
base.delete_file(out_dir + "/banners_word.js")
base.delete_file(out_dir + "/banners_cell.js")
base.delete_file(out_dir + "/banners_slide.js")
# Write sdk version mark file if needed
if (options.write_version):

View File

@ -16,7 +16,8 @@ def make():
if("" != config.option("branding")):
branding_dir = git_dir + '/' + config.option("branding") + '/server'
build_server_with_addons()
base.cmd_in_dir(server_dir, "npm", ["install"])
base.cmd_in_dir(server_dir, "grunt", ["--no-color", "-v"] + base.server_addons_param())
#env variables
product_version = base.get_env('PRODUCT_VERSION')
@ -29,17 +30,18 @@ def make():
cur_date = datetime.date.today().strftime("%m/%d/%Y")
base.replaceInFileRE(server_dir + "/Common/sources/commondefines.js", "const buildNumber = [0-9]*", "const buildNumber = " + build_number)
base.replaceInFileRE(server_dir + "/Common/sources/license.js", "const buildDate = '[0-9-/]*'", "const buildDate = '" + cur_date + "'")
base.replaceInFileRE(server_dir + "/Common/sources/commondefines.js", "const buildVersion = '[0-9.]*'", "const buildVersion = '" + product_version + "'")
server_build_dir = server_dir + "/build/server"
base.replaceInFileRE(server_build_dir + "/Common/sources/commondefines.js", "const buildNumber = [0-9]*", "const buildNumber = " + build_number)
base.replaceInFileRE(server_build_dir + "/Common/sources/license.js", "const buildDate = '[0-9-/]*'", "const buildDate = '" + cur_date + "'")
base.replaceInFileRE(server_build_dir + "/Common/sources/commondefines.js", "const buildVersion = '[0-9.]*'", "const buildVersion = '" + product_version + "'")
custom_public_key = branding_dir + '/debug.js'
if(base.is_exist(custom_public_key)):
base.copy_file(custom_public_key, server_dir + '/Common/sources')
base.copy_file(custom_public_key, server_build_dir + '/Common/sources')
#node22 packaging has issue https://github.com/yao-pkg/pkg/issues/87
pkg_target = "node20"
pkg_target = "node14"
if ("linux" == base.host_platform()):
pkg_target += "-linux"
@ -49,25 +51,16 @@ def make():
if ("windows" == base.host_platform()):
pkg_target += "-win"
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_build_dir + "/DocService", "pkg", [".", "-t", pkg_target, "--options", "max_old_space_size=4096", "-o", "docservice"])
base.cmd_in_dir(server_build_dir + "/FileConverter", "pkg", [".", "-t", pkg_target, "-o", "converter"])
base.cmd_in_dir(server_build_dir + "/Metrics", "pkg", [".", "-t", pkg_target, "-o", "metrics"])
example_dir = base.get_script_dir() + "/../../document-server-integration/web/documentserver-example/nodejs"
base.delete_dir(example_dir + "/node_modules")
base.cmd_in_dir(example_dir, "npm", ["ci"])
base.cmd_in_dir(example_dir, "npm", ["install"])
base.cmd_in_dir(example_dir, "pkg", [".", "-t", pkg_target, "-o", "example"])
def build_server_with_addons():
addons = {}
addons["server"] = [True, False]
addons.update(base.get_server_addons())
for addon in addons:
if (addon):
addon_dir = base.get_script_dir() + "/../../" + addon
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():
build_server_with_addons()
server_dir = base.get_script_dir() + "/../../server"
base.cmd_in_dir(server_dir, "npm", ["install"])
base.cmd_in_dir(server_dir, "grunt", ["develop", "-v"] + base.server_addons_param())

View File

@ -1,75 +0,0 @@
#!/usr/bin/env python
import config
import base
import os
import sys
sys.path.append(os.path.dirname(__file__) + "/..")
import sln
import qmake
# make solution
def make(solution=""):
platforms = config.option("platform").split()
for platform in platforms:
if not platform in config.platforms:
continue
print("------------------------------------------")
print("BUILD_PLATFORM: " + platform)
print("------------------------------------------")
if ("" == solution):
solution = "./sln.json"
projects = sln.get_projects(solution, platform)
for pro in projects:
qmake_main_addon = ""
if (0 == platform.find("android")) and (-1 != pro.find("X2tConverter.pro")):
if config.check_option("config", "debug") and not config.check_option("config", "disable_x2t_debug_strip"):
print("[WARNING:] temporary enable strip for x2t library in debug")
qmake_main_addon += "build_strip_debug"
qmake.make(platform, pro, qmake_main_addon)
if config.check_option("platform", "ios") and config.check_option("config", "bundle_xcframeworks"):
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
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

View File

@ -182,9 +182,6 @@ def extend_option(name, value):
else:
options[name] = value
def set_option(name, value):
options[name] = value
def branding():
branding = option("branding-name")
if ("" == branding):
@ -222,10 +219,6 @@ def parse_defaults():
options[name] = options[name].replace("default", defaults_options[name])
else:
options[name] = defaults_options[name]
if ("config_addon" in defaults_options):
extend_option("config", defaults_options["config_addon"])
return
def is_cef_107():

View File

@ -13,18 +13,14 @@ import cef
import icu
import openssl
import curl
import websocket_all
import websocket
import v8
import html2
import iwork
import md
import hunspell
import glew
import harfbuzz
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"):
@ -45,20 +41,14 @@ def make():
openssl.make()
v8.make()
html2.make()
iwork.make(False)
md.make()
hunspell.make(False)
harfbuzz.make()
glew.make()
hyphen.make()
googletest.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()
websocket_all.make()
websocket.make()
return

View File

@ -1,170 +0,0 @@
#!/usr/bin/env python
import sys
sys.path.append('../../../scripts')
import base
import os
import re
def get_android_ndk_version():
env_val = base.get_env("ANDROID_NDK_ROOT")
if (env_val == ""):
env_val = "21.1.6352462"
return env_val.strip("/").split("/")[-1]
def get_android_ndk_version_major():
val = get_android_ndk_version().split(".")[0]
val = re.sub("[^0-9]", "", val)
return int(val)
def get_sdk_api():
if (23 > get_android_ndk_version_major()):
return "21"
return "23"
global archs
archs = ["arm64", "arm", "x86_64", "x86"]
global platforms
platforms = {
"arm64" : {
"abi" : "arm64-v8a",
"target" : "aarch64-linux-android",
"dst" : "arm64_v8a",
"api" : get_sdk_api(),
"old" : "aarch64-linux-android"
},
"arm" : {
"abi" : "armeabi-v7a",
"target" : "armv7a-linux-androideabi",
"dst" : "armv7",
"api" : get_sdk_api(),
"old" : "arm-linux-android"
},
"x86_64" : {
"arch" : "x86_64",
"target" : "x86_64-linux-android",
"dst" : "x86_64",
"api" : get_sdk_api(),
"old" : "x86_64-linux-android"
},
"x86" : {
"arch" : "x86",
"target" : "i686-linux-android",
"dst" : "x86",
"api" : get_sdk_api(),
"old" : "i686-linux-android"
}
}
# todo: check arm host!
global host
if ("linux" == base.host_platform()):
host = {
"name" : "linux",
"arch" : "linux-x86_64"
}
else:
host = {
"name" : "darwin",
"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:
value.append(key + "=" + opts[key])
return value
def get_options_array_as_string(opts):
return " ".join(opts)
def ndk_dir():
return base.get_env("ANDROID_NDK_ROOT")
def sdk_dir():
ndk_path = ndk_dir()
if (-1 != ndk_path.find("/ndk/")):
return ndk_path + "/../.."
return ndk_path + "/.."
def toolchain_dir():
return ndk_dir() + "/toolchains/llvm/prebuilt/" + host["arch"]
def prepare_platform(arch, cpp_standard=11):
target = platforms[arch]["target"]
api = platforms[arch]["api"]
ndk_directory = ndk_dir()
toolchain = toolchain_dir()
base.set_env("TARGET", target)
base.set_env("TOOLCHAIN", toolchain)
base.set_env("NDK_STANDARD_ROOT", toolchain)
base.set_env("ANDROIDVER", api)
base.set_env("ANDROID_API", api)
base.set_env("AR", toolchain + "/bin/llvm-ar")
base.set_env("AS", toolchain + "/bin/llvm-as")
base.set_env("LD", toolchain + "/bin/ld")
base.set_env("RANLIB", toolchain + "/bin/llvm-ranlib")
base.set_env("STRIP", toolchain + "/bin/llvm-strip")
base.set_env("CC", target + api + "-clang")
base.set_env("CXX", target + api + "-clang++")
ld_flags = "-Wl,--gc-sections,-rpath-link=" + toolchain + "/sysroot/usr/lib/"
if (23 > get_android_ndk_version_major()):
ld_flags += (" -L" + toolchain + "/" + platforms[arch]["old"] + "/lib")
ld_flags += (" -L" + toolchain + "/sysroot/usr/lib/" + platforms[arch]["old"] + "/" + api)
base.set_env("LDFLAGS", ld_flags)
base.set_env("PATH", toolchain + "/bin" + os.pathsep + base.get_env("PATH"))
cflags = [
"-Os",
"-ffunction-sections",
"-fdata-sections",
"-fvisibility=hidden",
"-Wno-unused-function",
"-fPIC",
"-I" + toolchain + "/sysroot/usr/include",
"-D__ANDROID_API__=" + api,
"-DANDROID"
]
cflags_string = " ".join(cflags)
cppflags_string = cflags_string
if (cpp_standard >= 11):
cppflags_string += " -std=c++11"
base.set_env("CFLAGS", cflags_string)
base.set_env("CXXFLAGS", cppflags_string)
base.set_env("CPPPLAGS", cflags_string)
return
def extend_cflags(params):
base.set_env("CFLAGS", base.get_env("CFLAGS") + " " + params)
base.set_env("CPPFLAGS", base.get_env("CFLAGS"))
return
def extend_cxxflags(params):
base.set_env("CXXFLAGS", base.get_env("CXXFLAGS") + " " + params)
return
def extend_ldflags(params):
base.set_env("LDFLAGS", base.get_env("LDFLAGS") + " " + params)
return

View File

@ -1,94 +0,0 @@
#!/usr/bin/env python
import sys
sys.path.append('../../../scripts')
import base
import os
import android_ndk
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/curl"
current_dir = os.path.abspath(current_dir)
if not current_dir.endswith("/"):
current_dir += "/"
lib_version = "curl-7_68_0"
lib_name = "curl-7.68.0"
def fetch():
if not base.is_dir(current_dir + lib_name):
base.cmd("curl", ["-L", "-s", "-o", current_dir + lib_name + ".tar.gz",
"https://github.com/curl/curl/releases/download/" + lib_version + "/" + lib_name + ".tar.gz"])
base.cmd("tar", ["xfz", current_dir + lib_name + ".tar.gz", "-C", current_dir])
return
def build_host():
return
def build_arch(arch):
dst_dir = current_dir + "build/android/" + android_ndk.platforms[arch]["dst"]
if base.is_dir(dst_dir):
return
android_ndk.prepare_platform(arch)
ndk_dir = android_ndk.ndk_dir()
toolchain = android_ndk.toolchain_dir()
base.set_env("ANDROID_NDK_HOME", ndk_dir)
base.set_env("ANDROID_NDK", ndk_dir)
arch_build_dir = os.path.abspath(current_dir + "build/android/tmp")
base.create_dir(arch_build_dir)
old_cur = os.getcwd()
os.chdir(current_dir + lib_name)
params = []
if ("arm64" == arch):
params.append("--host=aarch64-linux-android")
elif ("arm" == arch):
params.append("--host=arm-linux-androideabi")
elif ("x86_64" == arch):
params.append("--host=x86_64-linux-android")
elif ("x86" == arch):
params.append("--host=i686-linux-android")
openssl_dir = os.path.abspath(current_dir + "../openssl/build/android/" + android_ndk.platforms[arch]["dst"])
params.append("--enable-ipv6")
params.append("--enable-static")
params.append("--disable-shared")
params.append("--prefix=" + arch_build_dir)
params.append("--with-ssl=" + openssl_dir)
base.cmd("./configure", params)
base.cmd("make", ["clean"])
base.cmd("make", ["-j4"])
base.cmd("make", ["install"])
os.chdir(old_cur)
base.create_dir(dst_dir)
base.copy_file(arch_build_dir + "/lib/libcurl.a", dst_dir)
base.copy_dir(arch_build_dir + "/include", current_dir + "build/android/include")
base.delete_dir(arch_build_dir)
return
def make():
old_env = dict(os.environ)
fetch()
build_host()
for arch in android_ndk.archs:
build_arch(arch)
os.environ.clear()
os.environ.update(old_env)
return
if __name__ == "__main__":
make()

View File

@ -1,147 +0,0 @@
#!/usr/bin/env python
import sys
sys.path.append('../../../scripts')
import base
import os
import android_ndk
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/icu/android"
current_dir = os.path.abspath(current_dir)
if not current_dir.endswith("/"):
current_dir += "/"
icu_major = "58"
icu_minor = "3"
options = {
"--enable-strict" : "no",
"--enable-extras" : "no",
"--enable-draft" : "yes",
"--enable-samples" : "no",
"--enable-tests" : "no",
"--enable-renaming" : "yes",
"--enable-icuio" : "no",
"--enable-layoutex" : "no",
"--with-library-bits" : "nochange",
"--with-library-suffix" : "",
"--enable-static" : "yes",
"--enable-shared" : "no",
"--with-data-packaging" : "archive"
}
cpp_flags_base = [
"-Os",
"-ffunction-sections",
"-fdata-sections",
"-fvisibility=hidden",
"-fPIC"
]
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",
"-DUCONFIG_NO_TRANSLITERATION=0",
"-DU_STATIC_IMPLEMENTATION"
]
def fetch_icu():
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.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():
cross_build_dir = os.path.abspath(current_dir + "icu/cross_build")
if not base.is_dir(cross_build_dir):
base.create_dir(cross_build_dir)
os.chdir(cross_build_dir)
ld_flags = "-pthread"
if ("linux" == base.host_platform()):
ld_flags += " -Wl,--gc-sections"
else:
# gcc on OSX does not support --gc-sections
ld_flags += " -Wl,-dead_strip"
base.set_env("LDFLAGS", ld_flags)
base.set_env("CPPFLAGS", android_ndk.get_options_array_as_string(cpp_flags_base + cpp_flags))
host_type = "Linux"
if ("mac" == base.host_platform()):
host_type = "MacOSX/GCC"
base.cmd("../source/runConfigureICU", [host_type, "--prefix=" + cross_build_dir] + android_ndk.get_options_dict_as_array(options))
base.cmd("make", ["-j4"])
base.cmd("make", ["install"], True)
base.create_dir(current_dir + "build")
base.copy_dir(cross_build_dir + "/include", current_dir + "build/include")
os.chdir(current_dir)
return
def build_arch(arch):
dst_dir = current_dir + "build/" + android_ndk.platforms[arch]["dst"]
if base.is_dir(dst_dir):
return
android_ndk.prepare_platform(arch)
android_ndk.extend_cflags(" ".join(cpp_flags))
ndk_dir = android_ndk.ndk_dir()
toolchain = android_ndk.toolchain_dir()
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] +
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)
base.create_dir(dst_dir)
base.copy_file(arch_build_dir + "/lib/libicuuc.a", dst_dir)
base.copy_file(arch_build_dir + "/stubdata/libicudata.a", dst_dir)
base.copy_file(arch_build_dir + "/data/out/icudt" + icu_major + "l.dat", dst_dir)
base.delete_dir(arch_build_dir)
return
def make():
if not base.is_dir(current_dir):
base.create_dir(current_dir)
old_env = dict(os.environ)
fetch_icu()
build_host()
for arch in android_ndk.archs:
build_arch(arch)
os.environ.clear()
os.environ.update(old_env)
return
if __name__ == "__main__":
make()

View File

@ -1,94 +0,0 @@
#!/usr/bin/env python
import sys
sys.path.append('../../../scripts')
import base
import os
import android_ndk
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/openssl"
current_dir = os.path.abspath(current_dir)
if not current_dir.endswith("/"):
current_dir += "/"
lib_name="openssl-1.1.1t"
options = [
"no-shared",
"no-tests",
"enable-ssl3",
"enable-ssl3-method",
"enable-md2",
"no-asm"
]
def fetch():
if not base.is_dir(current_dir + lib_name):
base.cmd("curl", ["-L", "-s", "-o", current_dir + lib_name + ".tar.gz",
"https://www.openssl.org/source/" + lib_name + ".tar.gz"])
base.cmd("tar", ["xfz", current_dir + lib_name + ".tar.gz", "-C", current_dir])
return
def build_host():
# not needed, just create directories
if not base.is_dir(current_dir + "/build"):
base.create_dir(current_dir + "/build")
if not base.is_dir(current_dir + "/build/android"):
base.create_dir(current_dir + "/build/android")
return
def build_arch(arch):
dst_dir = current_dir + "build/android/" + android_ndk.platforms[arch]["dst"]
if base.is_dir(dst_dir):
return
android_ndk.prepare_platform(arch)
ndk_dir = android_ndk.ndk_dir()
toolchain = android_ndk.toolchain_dir()
base.set_env("ANDROID_NDK_HOME", ndk_dir)
base.set_env("ANDROID_NDK", ndk_dir)
arch_build_dir = os.path.abspath(current_dir + "build/android/tmp")
base.create_dir(arch_build_dir)
old_cur = os.getcwd()
os.chdir(current_dir + lib_name)
base.cmd("./Configure", ["android-" + arch, "--prefix=" + arch_build_dir, "-D__ANDROID_API__=" + android_ndk.platforms[arch]["api"]] + options)
base.replaceInFile("./Makefile", "LIB_CFLAGS=", "LIB_CFLAGS=-fvisibility=hidden ")
base.replaceInFile("./Makefile", "LIB_CXXFLAGS=", "LIB_CXXFLAGS=-fvisibility=hidden ")
base.cmd("make", ["clean"])
base.cmd("make", ["-j4"])
base.cmd("make", ["install"])
os.chdir(old_cur)
base.create_dir(dst_dir)
base.create_dir(dst_dir + "/lib")
base.copy_file(arch_build_dir + "/lib/libcrypto.a", dst_dir + "/lib")
base.copy_file(arch_build_dir + "/lib/libssl.a", dst_dir + "/lib")
base.copy_dir(arch_build_dir + "/include", dst_dir + "/include")
base.delete_dir(arch_build_dir)
return
def make():
old_env = dict(os.environ)
fetch()
build_host()
for arch in android_ndk.archs:
build_arch(arch)
os.environ.clear()
os.environ.update(old_env)
return
if __name__ == "__main__":
make()

View File

@ -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")
@ -89,15 +89,10 @@ def make():
correct_install_includes_win(base_dir, "win_32")
if config.check_option("platform", "linux_64") and not base.is_dir("../build/linux_64"):
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("./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"] + addon_compile + ["install"])
base.cmd("./b2", ["--prefix=./../build/linux_64", "link=static", "cxxflags=-fPIC", "install"])
# TODO: support x86
if config.check_option("platform", "linux_arm64") and not base.is_dir("../build/linux_arm64"):

View File

@ -0,0 +1,108 @@
#!/usr/bin/env python
import sys
sys.path.append('../..')
import config
import base
import os
platforms = {
"arm64_v8a" : {
"name" : "arm64-v8a",
"toolset" : "arm64v8a",
"clang_triple" : "aarch64-linux-android21",
"tool_triple" : "aarch64-linux-android",
"abi" : "aapcs",
"arch" : "arm",
"address_model" : "64",
"compiler_flags" : "",
"linker_flags" : ""
},
"armv7" : {
"name" : "armeabi-v7a",
"toolset" : "armeabiv7a",
"clang_triple" : "armv7a-linux-androideabi16",
"tool_triple" : "arm-linux-androideabi",
"abi" : "aapcs",
"arch" : "arm",
"address_model" : "32",
"compiler_flags" : "-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp",
"linker_flags" : "-Wl,--fix-cortex-a8"
},
"x86" : {
"name" : "x86",
"toolset" : "x86",
"clang_triple" : "i686-linux-android16",
"tool_triple" : "i686-linux-android",
"abi" : "sysv",
"arch" : "x86",
"address_model" : "32",
"compiler_flags" : "",
"linker_flags" : ""
},
"x86_64" : {
"name" : "x86_64",
"toolset" : "x8664",
"clang_triple" : "x86_64-linux-android21",
"tool_triple" : "x86_64-linux-android",
"abi" : "sysv",
"arch" : "x86",
"address_model" : "64",
"compiler_flags" : "",
"linker_flags" : ""
}
}
base_dir = base.get_script_dir()
def make(platform):
tmp_build_dir = base_dir + "/core_common/modules/boost"
if (base.is_dir(tmp_build_dir)):
base.delete_dir(tmp_build_dir)
base.copy_dir(base_dir + "/../tools/android/boost", tmp_build_dir)
current_platform = platforms[platform]
if (base.host_platform() == "mac"):
source = "prebuilt/linux-x86_64"
dest = "prebuilt/darwin-x86_64"
base.replaceInFile(tmp_build_dir + "/user-config.jam", source, dest)
base.replaceInFile(tmp_build_dir + "/bin/hide/as", source, dest)
base.replaceInFile(tmp_build_dir + "/bin/hide/strip", source, dest)
base.replaceInFile(tmp_build_dir + "/bin/ar", source, dest)
base.replaceInFile(tmp_build_dir + "/bin/clang++", source, dest)
base.replaceInFile(tmp_build_dir + "/bin/ranlib", source, dest)
build_dir_tmp = tmp_build_dir + "/tmp"
base.cmd("./bootstrap.sh", ["--with-libraries=filesystem,system,date_time,regex", "--prefix=../build/android_" + platform])
base.cmd("./b2", ["headers"])
base.cmd("./b2", ["--clean"])
old_path = base.get_env("PATH")
base.set_env("PATH", tmp_build_dir + "/bin:" + old_path)
base.set_env("NDK_DIR", base.get_env("ANDROID_NDK_ROOT"))
base.set_env("BFA_CLANG_TRIPLE_FOR_ABI", current_platform["clang_triple"])
base.set_env("BFA_TOOL_TRIPLE_FOR_ABI", current_platform["tool_triple"])
base.set_env("BFA_COMPILER_FLAGS_FOR_ABI", current_platform["compiler_flags"])
base.set_env("BFA_LINKER_FLAGS_FOR_ABI", current_platform["linker_flags"])
print(current_platform)
base.cmd("./b2", ["-q", "-j4",
"toolset=clang-" + current_platform["toolset"],
"binary-format=elf",
"address-model=" + current_platform["address_model"],
"architecture=" + current_platform["arch"],
"abi=" + current_platform["abi"],
"link=static",
"threading=multi",
"target-os=android",
"--user-config=" + tmp_build_dir + "/user-config.jam",
"--ignore-site-config",
"--layout=system",
"install"], True)
base.set_env("PATH", old_path)
base.delete_dir(tmp_build_dir)
return

View File

@ -5,7 +5,7 @@ sys.path.append('../..')
import config
import base
import os
import qmake
import build
def make(src_dir, modules, build_platform="android", qmake_addon=""):
old_cur = os.getcwd()
@ -23,13 +23,17 @@ def make(src_dir, modules, build_platform="android", qmake_addon=""):
pro_file_content.append("TARGET = boost_" + module)
pro_file_content.append("TEMPLATE = lib")
pro_file_content.append("CONFIG += staticlib")
if (build_platform == "android"):
pro_file_content.append("DEFINES += \"_HAS_AUTO_PTR_ETC=0\"")
pro_file_content.append("")
pro_file_content.append("CORE_ROOT_DIR = $$PWD/../../../../../..")
pro_file_content.append("PWD_ROOT_DIR = $$PWD")
pro_file_content.append("include($$PWD/../../../../../base.pri)")
pro_file_content.append("")
pro_file_content.append("MAKEFILE=$$PWD/build.makefile_$$CORE_BUILDS_PLATFORM_PREFIX")
pro_file_content.append("core_debug:MAKEFILE=$$join(MAKEFILE, MAKEFILE, \"\", \"_debug_\")")
pro_file_content.append("build_xp:MAKEFILE=$$join(MAKEFILE, MAKEFILE, \"\", \"_xp\")")
pro_file_content.append("OO_BRANDING_SUFFIX = $$(OO_BRANDING)")
pro_file_content.append("!isEmpty(OO_BRANDING_SUFFIX):MAKEFILE=$$join(MAKEFILE, MAKEFILE, \"\", \"$$OO_BRANDING_SUFFIX\")")
pro_file_content.append("")
pro_file_content.append("BOOST_SOURCES=$$PWD/../..")
pro_file_content.append("INCLUDEPATH += $$BOOST_SOURCES")
pro_file_content.append("INCLUDEPATH += $$PWD/include")
@ -39,7 +43,7 @@ def make(src_dir, modules, build_platform="android", qmake_addon=""):
pro_file_content.append("DESTDIR = $$BOOST_SOURCES/../build/" + build_platform + "/lib/$$CORE_BUILDS_PLATFORM_PREFIX")
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)
build.make_pro_file("./", module + ".pro", qmake_addon)
os.chdir(old_cur)
return

View File

@ -2,19 +2,21 @@
import sys
sys.path.append('../..')
sys.path.append('android')
import config
import subprocess
import os
import base
import curl_android
def make():
path = base.get_script_dir() + "/../../core/Common/3dParty/curl"
old_cur = os.getcwd()
os.chdir(path)
if (-1 != config.option("platform").find("android")):
curl_android.make()
if base.is_dir(path + "/build/android"):
os.chdir(old_cur)
return
subprocess.call(["./build-android-curl.sh"])
elif (-1 != config.option("platform").find("ios")):
if base.is_dir(path + "/build/ios"):
os.chdir(old_cur)

View File

@ -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"

View File

@ -1,366 +0,0 @@
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 = "ios-cmake/ios.toolchain.cmake"
# android cmake toolchain
ANDROID_CMAKE_TOOLCHAIN_FILE = base.get_env("ANDROID_NDK_ROOT") + "/build/cmake/android.toolchain.cmake"
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":
cmake_args_ext += ["-A", "x64"]
elif platform == "win_32":
cmake_args_ext += ["-A", "Win32"]
# 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"]
if base.is_os_arm():
cmake_args_ext += [
"-DCMAKE_OSX_ARCHITECTURES=x86_64"
]
elif platform == "mac_arm64":
cmake_args_ext += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0"]
# 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")
# run cmake
base.cmd("cmake", cmake_args + cmake_args_ext)
# build
if "Unix Makefiles" in cmake_args_ext:
base.cmd("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"):
build_func("win_64", cmake_args)
# win_32
if config.check_option("platform", "win_32"):
build_func("win_32", 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
]
# 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)"
)
# 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 make():
print("[fetch & build]: heif")
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/heif"
old_dir = os.getcwd()
os.chdir(base_dir)
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_dir("ios-cmake"):
fetch_repo("https://github.com/leetal/ios-cmake.git", IOS_CMAKE_VERSION)
global IOS_CMAKE_TOOLCHAIN_FILE
IOS_CMAKE_TOOLCHAIN_FILE = os.path.join(base_dir, IOS_CMAKE_TOOLCHAIN_FILE)
# 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()

View File

@ -7,27 +7,7 @@ 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()

View File

@ -3,11 +3,6 @@ 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()
@ -16,8 +11,6 @@ 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):

View File

@ -2,52 +2,26 @@
import sys
sys.path.append('../..')
sys.path.append('android')
import config
import base
import os
import glob
import icu_android
def fetch_icu(major, minor):
if (base.is_dir("./icu2")):
base.delete_dir_with_access_error("icu2")
base.cmd("git", ["clone", "--depth", "1", "--branch", "maint/maint-" + major, "https://github.com/unicode-org/icu.git", "./icu2"])
base.copy_dir("./icu2/icu4c", "./icu")
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():
if base.is_dir("icu"):
base.delete_dir_with_access_error("icu")
# remove build
for child in glob.glob("./*"):
if base.is_dir(child):
base.delete_dir(child)
return
def make():
print("[fetch & build]: icu")
if (-1 != config.option("platform").find("android")):
icu_android.make()
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/icu"
old_cur = os.getcwd()
os.chdir(base_dir)
base.check_module_version("3", clear_module)
if (-1 != config.option("platform").find("android")):
icu_android.make()
os.chdir(base_dir)
icu_major = "58"
icu_minor = "3"
icu_minor = "2"
if not base.is_dir("icu"):
fetch_icu(icu_major, icu_minor)
base.cmd("svn", ["export", "https://github.com/unicode-org/icu/tags/release-" + icu_major + "-" + icu_minor + "/icu4c", "./icu", "--non-interactive", "--trust-server-cert"])
if ("windows" == base.host_platform()):
platformToolset = "v140"
@ -91,13 +65,8 @@ def make():
if not base.is_dir(base_dir + "/linux_64"):
base.create_dir(base_dir + "/icu/cross_build")
os.chdir("icu/cross_build")
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++"
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)
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)
base.create_dir(base_dir + "/linux_64")

View File

@ -0,0 +1,172 @@
#!/usr/bin/env python
import sys
sys.path.append('../..')
import base
import os
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/icu/android"
toolshains_dir = current_dir + "/toolchains"
icu_major = "58"
icu_minor = "2"
icu_is_shared = False
current_path = base.get_env("PATH")
platforms = {
"arm64" : {
"arch" : "aarch64-linux-android",
"bin" : "aarch64-linux-android"
},
"arm" : {
"arch" : "arm-linux-androideabi",
"bin" : "arm-linux-androideabi"
},
"x86_64" : {
"arch" : "x86_64-linux-android",
"bin" : "x86_64-linux-android"
},
"x86" : {
"arch" : "x86-linux-android",
"bin" : "i686-linux-android"
}
}
def build_arch(arch, api_version):
print("icu build: " + arch + " ----------------------------------------")
if base.is_dir(current_dir + "/icu/" + arch):
base.delete_dir(current_dir + "/icu/" + arch)
base.create_dir(current_dir + "/icu/" + arch)
os.chdir(current_dir + "/icu/" + arch)
base.cmd(base.get_env("ANDROID_NDK_ROOT") + "/build/tools/make-standalone-toolchain.sh", [
"--platform=android-" + api_version,
"--install-dir=" + current_dir + "/toolchain/" + arch,
"--toolchain=" + platforms[arch]["arch"],
"--force"
])
base.set_env("PATH", current_dir + "/toolchain/" + arch + "/bin:" + current_path)
command_args = "--prefix=" + current_dir + "/build_tmp/" + arch + " --host=!!!MASK!!! --with-cross-build=" + current_dir + "/icu/cross_build CFLAGS=-Os CXXFLAGS=--std=c++11 CC=!!!MASK!!!-clang CXX=!!!MASK!!!-clang++ AR=!!!MASK!!!-ar RANLIB=!!!MASK!!!-ranlib"
if not icu_is_shared:
command_args += " --enable-static --enable-shared=no --with-data-packaging=archive CFLAGS=-fPIC CXXFLAGS=-fPIC"
command_args = command_args.replace("!!!MASK!!!", platforms[arch]["bin"])
base.cmd("../source/configure", command_args.split())
base.cmd("make", ["-j4"])
base.cmd("make", ["install"])
base.set_env("PATH", current_path)
os.chdir(current_dir)
return
def make():
if not base.is_dir(current_dir):
base.create_dir(current_dir)
if base.is_dir(current_dir + "/build"):
return
current_dir_old = os.getcwd()
print("[fetch & build]: icu_android")
os.chdir(current_dir)
if not base.is_dir("icu"):
base.cmd("svn", ["export", "https://github.com/unicode-org/icu/tags/release-" + icu_major + "-" + icu_minor + "/icu4c", "./icu", "--non-interactive", "--trust-server-cert"])
if ("linux" == base.host_platform()):
base.replaceInFile(current_dir + "/icu/source/i18n/digitlst.cpp", "xlocale", "locale")
#if ("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\",")
if not base.is_dir(current_dir + "/icu/cross_build"):
base.create_dir(current_dir + "/icu/cross_build")
os.chdir(current_dir + "/icu/cross_build")
base.cmd("../source/runConfigureICU", ["Linux" if "linux" == base.host_platform() else "MacOSX",
"--prefix=" + current_dir + "/icu/cross_build", "CFLAGS=-Os CXXFLAGS=--std=c++11"])
base.cmd("make", ["-j4"])
base.cmd("make", ["install"], True)
os.chdir(current_dir)
build_arch("arm64", "21")
build_arch("arm", "16")
build_arch("x86_64","21")
build_arch("x86", "16")
os.chdir(current_dir)
base.create_dir(current_dir + "/build")
base.copy_dir(current_dir + "/build_tmp/arm64/include", current_dir + "/build/include")
if icu_is_shared:
base.create_dir(current_dir + "/build/arm64_v8a")
base.copy_file(current_dir + "/build_tmp/arm64/lib/libicudata.so." + icu_major + "." + icu_minor, current_dir + "/build/arm64_v8a/libicudata.so")
base.copy_file(current_dir + "/build_tmp/arm64/lib/libicuuc.so." + icu_major + "." + icu_minor, current_dir + "/build/arm64_v8a/libicuuc.so")
base.create_dir(current_dir + "/build/armv7")
base.copy_file(current_dir + "/build_tmp/arm/lib/libicudata.so." + icu_major + "." + icu_minor, current_dir + "/build/armv7/libicudata.so")
base.copy_file(current_dir + "/build_tmp/arm/lib/libicuuc.so." + icu_major + "." + icu_minor, current_dir + "/build/armv7/libicuuc.so")
base.create_dir(current_dir + "/build/x86_64")
base.copy_file(current_dir + "/build_tmp/x86_64/lib/libicudata.so." + icu_major + "." + icu_minor, current_dir + "/build/x86_64/libicudata.so")
base.copy_file(current_dir + "/build_tmp/x86_64/lib/libicuuc.so." + icu_major + "." + icu_minor, current_dir + "/build/x86_64/libicuuc.so")
base.create_dir(current_dir + "/build/x86")
base.copy_file(current_dir + "/build_tmp/x86/lib/libicudata.so." + icu_major + "." + icu_minor, current_dir + "/build/x86/libicudata.so")
base.copy_file(current_dir + "/build_tmp/x86/lib/libicuuc.so." + icu_major + "." + icu_minor, current_dir + "/build/x86/libicuuc.so")
# patch elf information
os.chdir(current_dir + "/build")
base.cmd("git", ["clone", "https://github.com/NixOS/patchelf.git"])
os.chdir("./patchelf")
base.cmd("./bootstrap.sh")
base.cmd("./configure", ["--prefix=" + current_dir + "/build/patchelf/usr"])
base.cmd("make")
base.cmd("make", ["install"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicudata.so", "./../arm64_v8a/libicudata.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicuuc.so", "./../arm64_v8a/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--replace-needed", "libicudata.so." + icu_major, "libicudata.so", "./../arm64_v8a/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicudata.so", "./../armv7/libicudata.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicuuc.so", "./../armv7/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--replace-needed", "libicudata.so." + icu_major, "libicudata.so", "./../armv7/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicudata.so", "./../x86_64/libicudata.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicuuc.so", "./../x86_64/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--replace-needed", "libicudata.so." + icu_major, "libicudata.so", "./../x86_64/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicudata.so", "./../x86/libicudata.so"])
base.cmd("./usr/bin/patchelf", ["--set-soname", "libicuuc.so", "./../x86/libicuuc.so"])
base.cmd("./usr/bin/patchelf", ["--replace-needed", "libicudata.so." + icu_major, "libicudata.so", "./../x86/libicuuc.so"])
base.delete_dir(current_dir + "/build/patchelf")
if not icu_is_shared:
base.create_dir(current_dir + "/build/arm64_v8a")
base.copy_file(current_dir + "/build_tmp/arm64/lib/libicudata.a", current_dir + "/build/arm64_v8a/libicudata.a")
base.copy_file(current_dir + "/build_tmp/arm64/lib/libicuuc.a", current_dir + "/build/arm64_v8a/libicuuc.a")
base.copy_file(current_dir + "/icu/arm64/data/out/icudt58l.dat", current_dir + "/build/arm64_v8a/icudt58l.dat")
base.create_dir(current_dir + "/build/armv7")
base.copy_file(current_dir + "/build_tmp/arm/lib/libicudata.a", current_dir + "/build/armv7/libicudata.a")
base.copy_file(current_dir + "/build_tmp/arm/lib/libicuuc.a", current_dir + "/build/armv7/libicuuc.a")
base.copy_file(current_dir + "/icu/arm/data/out/icudt58l.dat", current_dir + "/build/armv7/icudt58l.dat")
base.create_dir(current_dir + "/build/x86_64")
base.copy_file(current_dir + "/build_tmp/x86_64/lib/libicudata.a", current_dir + "/build/x86_64/libicudata.a")
base.copy_file(current_dir + "/build_tmp/x86_64/lib/libicuuc.a", current_dir + "/build/x86_64/libicuuc.a")
base.copy_file(current_dir + "/icu/x86_64/data/out/icudt58l.dat", current_dir + "/build/x86_64/icudt58l.dat")
base.create_dir(current_dir + "/build/x86")
base.copy_file(current_dir + "/build_tmp/x86/lib/libicudata.a", current_dir + "/build/x86/libicudata.a")
base.copy_file(current_dir + "/build_tmp/x86/lib/libicuuc.a", current_dir + "/build/x86/libicuuc.a")
base.copy_file(current_dir + "/icu/x86/data/out/icudt58l.dat", current_dir + "/build/x86/icudt58l.dat")
os.chdir(current_dir_old)
return

View File

@ -35,7 +35,7 @@ def restore_icu_defs(current_dir):
return
icu_major = "58"
icu_minor = "3"
icu_minor = "2"
current_dir_old = os.getcwd()
current_dir = base.get_script_dir() + "/../../core/Common/3dParty/icu"
@ -47,7 +47,7 @@ if not base.is_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", "--enable-static", "CFLAGS=-Os CXXFLAGS=--std=c++11"])
"--prefix=" + current_dir + "/mac_cross_64", "CFLAGS=-Os CXXFLAGS=--std=c++11"])
change_icu_defs(current_dir + "/mac_cross_64", "x86_64")
@ -60,8 +60,8 @@ if not base.is_dir(current_dir + "/mac_cross_64"):
os.chdir(current_dir + "/icu/source")
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm_64",
"--with-cross-build=" + current_dir + "/mac_cross_64", "--enable-static", "VERBOSE=1"])
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm_64",
"--with-cross-build=" + current_dir + "/mac_cross_64", "VERBOSE=1"])
change_icu_defs(current_dir + "/icu/source", "arm64")
@ -85,22 +85,12 @@ 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")

View File

@ -1,38 +0,0 @@
#!/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)

View File

@ -1,124 +0,0 @@
#!/usr/bin/env python
import sys
sys.path.append('../..')
import config
import base
import os
def docker_build(image_name, dockerfile_dir, base_dir):
base.cmd("docker", ["build", "-t", image_name, dockerfile_dir])
vlc_dir = base_dir + "/vlc"
base.cmd("docker", ["run", "--rm", "-v", vlc_dir + ":/vlc", image_name])
base.cmd("docker", ["image", "rm", image_name])
return
def form_build_win(src_dir, dest_dir):
if not base.is_dir(dest_dir):
base.create_dir(dest_dir)
# copy include dir
base.copy_dir(src_dir + "/sdk/include", dest_dir + "/include")
# form lib dir
base.create_dir(dest_dir + "/lib")
base.copy_file(src_dir + "/sdk/lib/libvlc.lib", dest_dir + "/lib/vlc.lib")
base.copy_file(src_dir + "/sdk/lib/libvlccore.lib", dest_dir + "/lib/vlccore.lib")
base.copy_dir(src_dir + "/plugins", dest_dir + "/lib/plugins")
base.copy_file(src_dir + "/libvlc.dll", dest_dir + "/lib")
base.copy_file(src_dir + "/libvlccore.dll", dest_dir + "/lib")
base.copy_file(src_dir + "/vlc-cache-gen.exe", dest_dir + "/lib")
# generate cache file 'plugins.dat' for plugins loading
base.cmd_exe(dest_dir + "/lib/vlc-cache-gen", [dest_dir + "/lib/plugins"])
return
def form_build_linux(src_dir, dest_dir):
if not base.is_dir(dest_dir):
base.create_dir(dest_dir)
# copy include dir
base.copy_dir(src_dir + "/include", dest_dir + "/include")
# copy and form lib dir
base.copy_dir(src_dir + "/lib", dest_dir + "/lib")
base.delete_dir(dest_dir + "/lib/pkgconfig")
base.delete_file(dest_dir + "/lib/vlc/libcompat.a")
def form_build_mac(src_dir, dest_dir):
if not base.is_dir(dest_dir):
base.create_dir(dest_dir)
# copy include dir
base.copy_dir(src_dir + "/include", dest_dir + "/include")
# copy and form lib dir
base.copy_dir(src_dir + "/lib", dest_dir + "/lib")
base.cmd("find", [dest_dir + "/lib", "-name", "\"*.la\"", "-type", "f", "-delete"])
base.delete_dir(dest_dir + "/lib/pkgconfig")
base.delete_file(dest_dir + "/lib/vlc/libcompat.a")
# generate cache file 'plugins.dat' for plugins loading
base.run_command("DYLD_LIBRARY_PATH=" + dest_dir + "/lib " + dest_dir + "/lib/vlc/vlc-cache-gen " + dest_dir + "/lib/vlc/plugins")
return
def make():
print("[fetch & build]: libvlc")
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/libvlc"
vlc_dir = base_dir + "/vlc"
vlc_version = "3.0.18"
tools_dir = base.get_script_dir() + "/../tools"
old_cur = os.getcwd()
os.chdir(base_dir)
if not base.is_dir(vlc_dir):
# temporary disable auto CRLF for Windows
if "windows" == base.host_platform():
autocrlf_old = base.run_command("git config --global core.autocrlf")['stdout']
base.cmd("git", ["config", "--global", "core.autocrlf", "false"])
base.cmd("git", ["clone", "https://code.videolan.org/videolan/vlc.git", "--branch", vlc_version])
if "windows" == base.host_platform():
base.cmd("git", ["config", "--global", "core.autocrlf", autocrlf_old])
base.create_dir("build")
base.copy_file("tools/ignore-cache-time.patch", "vlc")
# windows
if "windows" == base.host_platform():
if config.check_option("platform", "win_64"):
base.copy_file("tools/win_64/build.patch", "vlc")
docker_build("libvlc-win64", base_dir + "/tools/win_64", base_dir)
form_build_win(vlc_dir + "/build/win64/vlc-" + vlc_version, base_dir + "/build/win_64")
if config.check_option("platform", "win_32"):
base.copy_file("tools/win_32/build.patch", "vlc")
docker_build("libvlc-win32", base_dir + "/tools/win_32", base_dir)
form_build_win(vlc_dir + "/build/win32/vlc-" + vlc_version, base_dir + "/build/win_32")
# linux
if config.check_option("platform", "linux_64"):
base.copy_file(tools_dir + "/linux/elf/patchelf", "vlc")
base.copy_file("tools/linux_64/change-rpaths.sh", "vlc")
docker_build("libvlc-linux64", base_dir + "/tools/linux_64", base_dir)
form_build_linux(vlc_dir + "/build/linux_64", base_dir + "/build/linux_64")
# mac
if "mac" == base.host_platform():
os.chdir(vlc_dir)
base.cmd("git", ["restore", "src/modules/bank.c"])
base.cmd("patch", ["-p1", "src/modules/bank.c", "../tools/ignore-cache-time.patch"])
if config.check_option("platform", "mac_64"):
base.cmd("git", ["restore", "extras/package/macosx/build.sh"])
base.cmd("patch", ["-p1", "extras/package/macosx/build.sh", "../tools/mac_64/build.patch"])
base.create_dir("build/mac_64")
os.chdir("build/mac_64")
base.cmd("../../extras/package/macosx/build.sh", ["-c"])
form_build_mac(vlc_dir + "/build/mac_64/vlc_install_dir", base_dir + "/build/mac_64")
if config.check_option("platform", "mac_arm64"):
base.cmd("git", ["restore", "extras/package/macosx/build.sh"])
base.cmd("patch", ["-p1", "extras/package/macosx/build.sh", "../tools/mac_arm64/build.patch"])
base.create_dir("build/mac_arm64")
os.chdir("build/mac_arm64")
base.cmd("../../extras/package/macosx/build.sh", ["-c"])
form_build_mac(vlc_dir + "/build/mac_arm64/vlc_install_dir", base_dir + "/build/mac_arm64")
os.chdir(old_cur)
return

View File

@ -1,20 +0,0 @@
#!/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()

View File

@ -81,16 +81,8 @@ def make():
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"])
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++")
else:
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden")
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden")
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)

View File

@ -1,19 +1,18 @@
#!/usr/bin/env python
import sys
sys.path.append('../..')
sys.path.append('android')
import base
import config
import os
import subprocess
import openssl_android
def make():
path = base.get_script_dir() + "/../../core/Common/3dParty/openssl"
old_cur = os.getcwd()
os.chdir(path)
if (-1 != config.option("platform").find("android")):
openssl_android.make()
base.set_env("ANDROID_HOME", base.get_android_sdk_home())
if (-1 != config.option("platform").find("android") and not base.is_dir("./build/android")):
subprocess.call(["./build-android-openssl.sh"])
if (-1 != config.option("platform").find("ios") and not base.is_dir("./build/ios")):
subprocess.call(["./build-ios-openssl.sh"])

View File

@ -27,16 +27,8 @@ def make():
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/socketio"
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"])
base.cmd_in_dir(base_dir + "/socket.io-client-cpp", "git", ["submodule", "init"])
base.cmd_in_dir(base_dir + "/socket.io-client-cpp", "git", ["submodule", "update"])
base.cmd_in_dir(base_dir + "/socket.io-client-cpp/lib/asio", "git", ["checkout", "230c0d2ae035c5ce1292233fcab03cea0d341264"])
base.cmd_in_dir(base_dir + "/socket.io-client-cpp/lib/websocketpp", "git", ["checkout", "56123c87598f8b1dd471be83ca841ceae07f95ba"])
# patches
base.apply_patch(base_dir + "/socket.io-client-cpp/lib/websocketpp/websocketpp/impl/connection_impl.hpp", base_dir + "/patches/websocketpp.patch")
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")
# no tls realization (remove if socket.io fix this)
dst_dir = base_dir + "/socket.io-client-cpp/src_no_tls"

View File

@ -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")
@ -45,7 +45,7 @@ def is_use_clang():
gcc_version = base.get_gcc_version()
is_clang = "false"
if (gcc_version >= 6000 or "1" == config.option("use-clang")):
if (gcc_version >= 6000):
is_clang = "true"
print("gcc version: " + str(gcc_version) + ", use clang:" + is_clang)
@ -93,7 +93,6 @@ def make():
if not base.is_dir("depot_tools"):
base.cmd("git", ["clone", "https://chromium.googlesource.com/chromium/tools/depot_tools.git"])
v8_89.change_bootstrap()
if ("windows" == base.host_platform()):
# hack for 32 bit system!!!
if base.is_file("depot_tools/cipd.ps1"):
@ -119,7 +118,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"], True)
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
base.cmd("gclient", ["sync", "--force"], True)
else:
base.cmd("gclient", ["sync"], True)
@ -226,17 +225,13 @@ def make_xp():
if not base.is_dir("depot_tools"):
base.cmd("git", ["clone", "https://chromium.googlesource.com/chromium/tools/depot_tools.git"])
v8_89.change_bootstrap()
if ("windows" == base.host_platform()):
# hack for 32 bit system!!!
if base.is_file("depot_tools/cipd.ps1"):
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"
os.environ["PATH"] = os.pathsep.join([base_dir + "/depot_tools",
base_dir + path_to_python2,
base_dir + "/depot_tools/win_tools-2_7_13_chromium7_bin/python/bin",
config.option("vs-path") + "/../Common7/IDE",
os.environ["PATH"]])
@ -246,7 +241,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"], True)
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
base.cmd("gclient", ["sync", "--force"], True)
# save common py script
@ -269,14 +264,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)")):
programFilesDir = base.get_env("ProgramFiles(x86)")
dev_path = programFilesDir + "\\Microsoft Visual Studio 14.0\\Common7\\IDE"
if (base.is_dir(dev_path)):
os.environ["PATH"] = dev_path + os.pathsep + os.environ["PATH"]
]);
# add "SET CL=\"/D_ITERATOR_DEBUG_LEVEL=0\"" before devenv for disable _ITERATOR_DEBUG_LEVEL in debug
if config.check_option("platform", "win_64_xp"):

View File

@ -7,29 +7,6 @@ import base
import os
import subprocess
def change_bootstrap():
base.move_file("./depot_tools/bootstrap/manifest.txt", "./depot_tools/bootstrap/manifest.txt.bak")
content = "# changed by build_tools\n\n"
content += "$VerifiedPlatform windows-amd64 windows-arm64 linux-amd64 mac-amd64 mac-arm64\n\n"
content += "@Subdir python\n"
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"
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
def make_args(args, platform, is_64=True, is_debug=False):
args_copy = args[:]
if is_64:
@ -52,20 +29,12 @@ def make_args(args, platform, is_64=True, is_debug=False):
else:
args_copy.append("is_debug=false")
linux_clang = False
if (platform == "linux"):
args_copy.append("is_clang=true")
if "1" == config.option("use-clang"):
args_copy.append("use_sysroot=true")
linux_clang = True
else:
args_copy.append("use_sysroot=false")
args_copy.append("use_sysroot=false")
if (platform == "windows"):
args_copy.append("is_clang=false")
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):
@ -77,12 +46,6 @@ def ninja_windows_make(args, is_64=True, is_debug=False):
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")
win_toolset_wrapper_file = "build/toolchain/win/tool_wrapper.py"
win_toolset_wrapper_file_content = base.readFile("build/toolchain/win/tool_wrapper.py")
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"])
base.cmd("ninja", ["-C", directory_out])
base.delete_file("./" + directory_out + "/obj/v8_wrappers.ninja")
@ -119,13 +82,9 @@ def make():
if not base.is_dir(base_dir):
base.create_dir(base_dir)
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"])
change_bootstrap()
os.environ["PATH"] = base_dir + "/depot_tools" + os.pathsep + os.environ["PATH"]
@ -138,7 +97,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"], True)
base.cmd("git", ["config", "--system", "core.longpaths", "true"])
os.chdir("../")
v8_branch_version = "remotes/branch-heads/8.9"
if ("mac" == base.host_platform()):
@ -149,15 +108,9 @@ def make():
if ("windows" == base.host_platform()):
base.replaceInFile("v8/build/config/win/BUILD.gn", ":static_crt", ":dynamic_crt")
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")
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")
@ -169,6 +122,7 @@ 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"):

View File

@ -4,10 +4,12 @@ import sys
sys.path.append('../..')
import config
import base
#import ixwebsocket
#import socketrocket
import ixwebsocket
import socketrocket
import socket_io
config_file = base.get_script_dir() + "/../../core/Common/WebSocket/websocket.pri"
def make():
#ixwebsocket.make()
#socketrocket.make()

View File

@ -7,7 +7,6 @@ import deploy_builder
import deploy_server
import deploy_core
import deploy_mobile
import deploy_osign
def make():
if config.check_option("module", "desktop"):
@ -20,6 +19,4 @@ def make():
deploy_core.make()
if config.check_option("module", "mobile"):
deploy_mobile.make()
if config.check_option("module", "osign"):
deploy_osign.make()
return

View File

@ -39,12 +39,10 @@ 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")
@ -65,7 +63,7 @@ def make():
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") and not config.check_option("config", "bundle_dylibs")):
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")
@ -78,21 +76,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")
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder", "", "./dictionaries")
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder")
base.copy_dir(git_dir + "/document-templates/new/en-US", root_dir + "/empty")
# dictionaries
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries", True, False)
# js
base.copy_dir(base_dir + "/js/" + branding + "/builder/sdkjs", root_dir + "/sdkjs")
base.create_dir(root_dir + "/sdkjs/vendor")
@ -106,44 +95,22 @@ 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, "ios")
if (0 == platform.find("linux")):
base.linux_correct_rpath_docbuilder(root_dir)
base.generate_plist(root_dir)
if (0 == platform.find("mac")):
base.generate_plist(root_dir, "mac", max_depth=1)
base.mac_correct_rpath_x2t(root_dir)
base.mac_correct_rpath_docbuilder(root_dir)
base.create_x2t_js_cache(root_dir, "builder", platform)
# 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

View File

@ -30,18 +30,15 @@ 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")
@ -53,8 +50,7 @@ def make():
if ("windows" == base.host_platform()):
base.copy_files(core_dir + "/Common/3dParty/icu/" + platform + "/build/*.dll", archive_dir + "/")
else:
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_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")
@ -64,18 +60,11 @@ def make():
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, archive_dir, "x2ttester")
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.generate_plist(archive_dir, "mac", max_depth=1)
# 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")
if base.is_file(archive_dir + ".7z"):
base.delete_file(archive_dir + ".7z")
base.archive_folder(archive_dir + "/*", archive_dir + ".7z")
# dictionaries
base.copy_dictionaries(git_dir + "/dictionaries", archive_dir + "/dictionaries", True, False)
return

View File

@ -6,16 +6,30 @@ import os
import platform
import glob
def copy_lib_with_links(src_dir, dst_dir, lib, version):
lib_full_name = lib + "." + version
major_version = version[:version.find(".")]
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])
def deploy_marketplace_plugin(git_dir, root_dir):
# old manager
#base.copy_sdkjs_plugin(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins", root_dir + "/editors/sdkjs-plugins", "manager", True)
# plugin manager with local paths
sys_plugins_dir = root_dir + "/editors/sdkjs-plugins"
base.clone_marketplace_plugin(sys_plugins_dir, True, True, False)
# store with local paths
manager_dir = sys_plugins_dir + "/{AA2EA9B6-9EC2-415F-9762-634EE8D9A95E}"
store_dir_path = manager_dir + "/store"
if base.is_dir(store_dir_path):
base.delete_dir(store_dir_path)
base.create_dir(store_dir_path)
base.copy_dir_content(sys_plugins_dir + "/onlyoffice.github.io/store", store_dir_path, "", ".git")
base.delete_dir(store_dir_path + "/plugin")
base.delete_file(store_dir_path + "/build.bat")
for file in glob.glob(store_dir_path + "/*.html"):
base.replaceInFile(file, "https://onlyoffice.github.io/sdkjs-plugins/", "../../")
base.delete_dir_with_access_error(sys_plugins_dir + "/onlyoffice.github.io")
return
def make():
@ -40,7 +54,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 += "/"
@ -54,27 +68,23 @@ def make():
platform_postfix = platform + base.qt_dst_postfix()
build_libraries_path = core_build_dir + "/lib/" + platform_postfix
# x2t
base.create_dir(root_dir + "/converter")
base.copy_lib(build_libraries_path, root_dir + "/converter", "kernel")
base.copy_lib(build_libraries_path, root_dir + "/converter", "kernel_network")
base.copy_lib(build_libraries_path, root_dir + "/converter", "UnicodeConverter")
base.copy_lib(build_libraries_path, root_dir + "/converter", "graphics")
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", "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")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "kernel")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "kernel_network")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "UnicodeConverter")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "graphics")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "PdfFile")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "DjVuFile")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "XpsFile")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "HtmlFile2")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "HtmlRenderer")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "Fb2File")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "EpubFile")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "DocxRenderer")
if ("ios" == platform):
base.copy_lib(build_libraries_path, root_dir + "/converter", "x2t")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir + "/converter", "x2t")
else:
base.copy_exe(core_build_dir + "/bin/" + platform_postfix, root_dir + "/converter", "x2t")
@ -91,33 +101,27 @@ def make():
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") and not config.check_option("config", "bundle_dylibs")):
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")
# doctrenderer
if isWindowsXP:
base.copy_lib(build_libraries_path + "/xp", root_dir + "/converter", "doctrenderer")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix + "/xp", root_dir + "/converter", "doctrenderer")
else:
base.copy_lib(build_libraries_path, root_dir + "/converter", "doctrenderer")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, 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.generate_doctrenderer_config(root_dir + "/converter/DoctRenderer.config", "../editors/", "desktop")
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")
base.copy_dir(git_dir + "/core-fonts/opensans", 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")
base.create_dir(root_dir + "/dictionaries")
base.copy_dir_content(git_dir + "/dictionaries", root_dir + "/dictionaries", "", ".git")
base.copy_dir(git_dir + "/desktop-apps/common/package/fonts", root_dir + "/fonts")
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")):
@ -135,23 +139,25 @@ def make():
isUseQt = False
# libraries
base.copy_lib(build_libraries_path, root_dir, "hunspell")
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "ooxmlsignature")
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "ascdocumentscore")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "hunspell")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix + ("/xp" if isWindowsXP else ""), root_dir, "ooxmlsignature")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix + ("/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")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix + ("/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("Qt5Multimedia", root_dir)
base.qt_copy_lib("Qt5MultimediaWidgets", root_dir)
base.qt_copy_lib("Qt5Network", root_dir)
base.qt_copy_lib("Qt5OpenGL", root_dir)
@ -161,16 +167,12 @@ def make():
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("mediaservice", root_dir)
base.qt_copy_plugin("playlistformats", root_dir)
base.qt_copy_plugin("platformthemes", root_dir)
base.qt_copy_plugin("xcbglintegrations", root_dir)
if not base.check_congig_option_with_platfom(platform, "libvlc"):
base.qt_copy_lib("Qt5Multimedia", root_dir)
base.qt_copy_lib("Qt5MultimediaWidgets", root_dir)
base.qt_copy_plugin("mediaservice", root_dir)
base.qt_copy_plugin("playlistformats", root_dir)
base.qt_copy_plugin("styles", root_dir)
if (0 == platform.find("linux")):
@ -178,55 +180,48 @@ def make():
base.qt_copy_lib("Qt5X11Extras", root_dir)
base.qt_copy_lib("Qt5XcbQpa", root_dir)
base.qt_copy_icu(root_dir)
if not base.check_congig_option_with_platfom(platform, "libvlc"):
base.copy_files(base.get_env("QT_DEPLOY") + "/../lib/libqgsttools_p.so*", root_dir)
base.copy_files(base.get_env("QT_DEPLOY") + "/../lib/libqgsttools_p.so*", root_dir)
if (0 == platform.find("win")):
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")):
base.copy_file(git_dir + "/desktop-apps/win-linux/" + apps_postfix + "/DesktopEditors", root_dir + "/DesktopEditors")
if base.check_congig_option_with_platfom(platform, "libvlc"):
vlc_dir = git_dir + "/core/Common/3dParty/libvlc/build/" + platform + "/lib"
if ("" != base.get_env("VIDEO_PLAYER_VLC_DIR")):
vlc_dir = git_dir + "/desktop-sdk/ChromiumBasedEditors/videoplayerlib/vlc/"
if (0 == platform.find("win")):
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")):
base.copy_dir(vlc_dir + "/vlc/plugins", root_dir + "/plugins")
base.copy_file(vlc_dir + "/vlc/libcompat.a", root_dir + "/libcompat.a")
copy_lib_with_links(vlc_dir + "/vlc", root_dir, "libvlc_pulse.so", "0.0.0")
copy_lib_with_links(vlc_dir + "/vlc", root_dir, "libvlc_vdpau.so", "0.0.0")
copy_lib_with_links(vlc_dir + "/vlc", root_dir, "libvlc_xcb_events.so", "0.0.0")
copy_lib_with_links(vlc_dir, root_dir, "libvlc.so", "5.6.1")
copy_lib_with_links(vlc_dir, root_dir, "libvlccore.so", "9.0.1")
base.copy_file(vlc_dir + "/vlc/vlc-cache-gen", root_dir + "/vlc-cache-gen")
base.copy_file(vlc_dir + platform + "/bin/libvlc.dll", root_dir + "/libvlc.dll")
base.copy_file(vlc_dir + platform + "/bin/libvlccore.dll", root_dir + "/libvlccore.dll")
base.copy_file(vlc_dir + platform + "/bin/VLCQtCore.dll", root_dir + "/VLCQtCore.dll")
base.copy_file(vlc_dir + platform + "/bin/VLCQtWidgets.dll", root_dir + "/VLCQtWidgets.dll")
else:
base.copy_file(vlc_dir + platform + "/bin/libvlc.so", root_dir + "/libvlc.so")
base.copy_file(vlc_dir + platform + "/bin/libvlc.so.5", root_dir + "/libvlc.so.5")
base.copy_file(vlc_dir + platform + "/bin/libvlccore.so", root_dir + "/libvlccore.so")
base.copy_file(vlc_dir + platform + "/bin/libvlccore.so.8", root_dir + "/libvlccore.so.8")
base.copy_file(vlc_dir + platform + "/bin/VLCQtCore.so", root_dir + "/VLCQtCore.so")
base.copy_file(vlc_dir + platform + "/bin/VLCQtWidgets.so", root_dir + "/VLCQtWidgets.so")
if isWindowsXP:
base.copy_lib(build_libraries_path + "/mediaplayer/xp", root_dir, "videoplayer")
base.copy_lib(core_build_dir + "/lib/" + platform + "/mediaplayer/xp", root_dir, "videoplayer")
else:
base.copy_lib(build_libraries_path + "/mediaplayer", root_dir, "videoplayer")
base.copy_lib(core_build_dir + "/lib/" + platform + "/mediaplayer", root_dir, "videoplayer")
base.copy_dir(vlc_dir + platform + "/bin/plugins", root_dir + "/plugins")
else:
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "videoplayer")
base.copy_lib(core_build_dir + "/lib/" + platform_postfix + ("/xp" if isWindowsXP else ""), root_dir, "videoplayer")
base.create_dir(root_dir + "/editors")
base.copy_dir(base_dir + "/js/" + branding + "/desktop/sdkjs", root_dir + "/editors/sdkjs")
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)
base.copy_dir(git_dir + "/desktop-sdk/ChromiumBasedEditors/resources/local", root_dir + "/editors/sdkjs/common/Images/local")
base.create_dir(root_dir + "/editors/sdkjs-plugins")
if not isWindowsXP:
base.copy_marketplace_plugin(root_dir + "/editors/sdkjs-plugins", True, True, True)
base.copy_sdkjs_plugins(root_dir + "/editors/sdkjs-plugins", True, True, isWindowsXP)
base.copy_sdkjs_plugins(root_dir + "/editors/sdkjs-plugins", True, True)
# remove some default plugins
if base.is_dir(root_dir + "/editors/sdkjs-plugins/speech"):
base.delete_dir(root_dir + "/editors/sdkjs-plugins/speech")
@ -242,10 +237,10 @@ 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)
deploy_marketplace_plugin(git_dir, root_dir)
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")
if isWindowsXP:
base.create_dir(root_dir + "/providers")
@ -255,10 +250,7 @@ def make():
isUseJSC = False
if (0 == platform.find("mac")):
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)
file_size_doctrenderer = os.path.getsize(root_dir + "/converter/libdoctrenderer.dylib")
print("file_size_doctrenderer: " + str(file_size_doctrenderer))
if (file_size_doctrenderer < 5*1024*1024):
isUseJSC = True
@ -266,8 +258,6 @@ 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")
@ -281,8 +271,6 @@ def make():
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.generate_plist(root_dir, "mac", max_depth=2)
base.mac_correct_rpath_desktop(root_dir)
if isMacArmPlaformOnIntel:
@ -308,3 +296,4 @@ def make():
base.delete_file(root_dir + "/editors/sdkjs/slide/sdk-all.cache")
return

View File

@ -6,19 +6,7 @@ import base
def exclude_arch(directory, frameworks):
for lib in frameworks:
base.cmd("lipo", ["-remove", "arm64", directory + "/" + lib + ".framework/" + lib, "-o", directory + "/" + lib + ".framework/" + lib])
return
def deploy_fonts(git_dir, root_dir, platform=""):
base.create_dir(root_dir + "/fonts")
base.copy_file(git_dir + "/core-fonts/ASC.ttf", root_dir + "/fonts/ASC.ttf")
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")
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 +23,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,13 +45,11 @@ 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")
@ -84,7 +70,7 @@ def make():
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")
@ -95,13 +81,21 @@ def make():
# correct ios frameworks
if ("ios" == platform):
base.generate_plist(root_dir, "ios")
deploy_fonts(git_dir, root_dir)
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries", True, False)
base.generate_plist(root_dir)
if (0 == platform.find("mac")):
base.mac_correct_rpath_x2t(root_dir)
base.create_dir(root_dir + "/fonts")
base.copy_file(git_dir + "/core-fonts/ASC.ttf", root_dir + "/fonts/ASC.ttf")
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")
if (0 == platform.find("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")
for native_platform in platforms:
if native_platform == "android":
# make full version
@ -112,10 +106,9 @@ def make():
# js
base.copy_dir(base_dir + "/js/" + branding + "/mobile/sdkjs", root_dir + "/sdkjs")
# fonts
deploy_fonts(git_dir, root_dir, "android")
base.copy_dictionaries(git_dir + "/dictionaries", root_dir + "/dictionaries", True, False)
base.copy_dir(base_dir + "/js/" + branding + "/mobile/fonts", root_dir + "/fonts")
# app
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder", "", "./dictionaries")
base.generate_doctrenderer_config(root_dir + "/DoctRenderer.config", "./", "builder")
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")

View File

@ -1,60 +0,0 @@
#!/usr/bin/env python
import config
import base
def make():
base_dir = base.get_script_dir() + "/../out"
git_dir = base.get_script_dir() + "/../.."
core_dir = git_dir + "/core"
branding = config.branding()
platforms = config.option("platform").split()
for native_platform in platforms:
if not native_platform in config.platforms:
continue
root_dir = base_dir + "/" + native_platform + "/" + branding + "/osign"
if base.get_env("DESTDIR_BUILD_OVERRIDE") != "":
return
if (base.is_dir(root_dir)):
base.delete_dir(root_dir)
base.create_dir(root_dir)
qt_dir = base.qt_setup(native_platform)
platform = native_platform
core_build_dir = core_dir + "/build"
if ("" != config.option("branding")):
core_build_dir += ("/" + config.option("branding"))
platform_postfix = platform + base.qt_dst_postfix()
# x2t
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "osign")
# correct ios frameworks
if ("ios" == platform):
base.generate_plist(root_dir, "ios")
for native_platform in platforms:
if native_platform == "android":
# make full version
root_dir = base_dir + "/android/" + branding + "/osign"
if (base.is_dir(root_dir)):
base.delete_dir(root_dir)
base.create_dir(root_dir)
libs_dir = root_dir + "/lib"
base.create_dir(libs_dir + "/arm64-v8a")
base.copy_files(base_dir + "/android_arm64_v8a/" + branding + "/osign/*.so", libs_dir + "/arm64-v8a")
base.create_dir(libs_dir + "/armeabi-v7a")
base.copy_files(base_dir + "/android_armv7/" + branding + "/osign/*.so", libs_dir + "/armeabi-v7a")
base.create_dir(libs_dir + "/x86")
base.copy_files(base_dir + "/android_x86/" + branding + "/osign/*.so", libs_dir + "/x86")
base.create_dir(libs_dir + "/x86_64")
base.copy_files(base_dir + "/android_x86_64/" + branding + "/osign/*.so", libs_dir + "/x86_64")
break
return

View File

@ -5,7 +5,6 @@ import base
import re
import shutil
import glob
from tempfile import mkstemp
def make():
@ -41,22 +40,24 @@ def make():
build_server_dir = root_dir + '/server'
server_dir = base.get_script_dir() + "/../../server"
bin_server_dir = server_dir + "/build/server"
base.create_dir(build_server_dir + '/DocService')
base.copy_dir(server_dir + '/Common/config', build_server_dir + '/Common/config')
base.copy_dir(bin_server_dir + '/Common/config', build_server_dir + '/Common/config')
base.create_dir(build_server_dir + '/DocService')
base.copy_exe(server_dir + "/DocService", build_server_dir + '/DocService', "docservice")
base.copy_exe(bin_server_dir + "/DocService", build_server_dir + '/DocService', "docservice")
base.create_dir(build_server_dir + '/FileConverter')
base.copy_exe(server_dir + "/FileConverter", build_server_dir + '/FileConverter', "converter")
base.copy_exe(bin_server_dir + "/FileConverter", build_server_dir + '/FileConverter', "converter")
base.create_dir(build_server_dir + '/Metrics')
base.copy_exe(server_dir + "/Metrics", build_server_dir + '/Metrics', "metrics")
base.copy_dir(server_dir + '/Metrics/config', build_server_dir + '/Metrics/config')
base.copy_exe(bin_server_dir + "/Metrics", build_server_dir + '/Metrics', "metrics")
base.copy_dir(bin_server_dir + '/Metrics/config', build_server_dir + '/Metrics/config')
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")
base.copy_file(bin_server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node", build_server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node")
qt_dir = base.qt_setup(native_platform)
platform = native_platform
@ -77,13 +78,11 @@ 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")
@ -91,7 +90,7 @@ def make():
#if (native_platform == "linux_64"):
# base.generate_check_linux_system(git_dir + "/build_tools", converter_dir)
base.generate_doctrenderer_config(converter_dir + "/DoctRenderer.config", "../../../", "server", "", "../../../dictionaries")
base.generate_doctrenderer_config(converter_dir + "/DoctRenderer.config", "../../../", "server")
# icu
if (0 == platform.find("win")):
@ -102,36 +101,26 @@ def make():
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") and not config.check_option("config", "bundle_dylibs")):
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.generate_plist(converter_dir, "mac", max_depth=1)
# js
js_dir = root_dir
base.copy_dir(base_dir + "/js/" + branding + "/builder/sdkjs", js_dir + "/sdkjs")
base.copy_dir(base_dir + "/js/" + branding + "/builder/web-apps", js_dir + "/web-apps")
for file in glob.glob(js_dir + "/web-apps/apps/*/*/*.js.map") \
+ 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)
if ("1" == config.option("preinstalled-plugins")):
base.copy_sdkjs_plugins(js_dir + "/sdkjs-plugins", False, True)
base.copy_sdkjs_plugins_server(js_dir + "/sdkjs-plugins", False, True)
@ -143,6 +132,8 @@ def make():
base.download("https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.css", js_dir + "/sdkjs-plugins/v1/plugins.css")
base.support_old_versions_plugins(js_dir + "/sdkjs-plugins")
base.clone_marketplace_plugin(root_dir + "/sdkjs-plugins")
# tools
tools_dir = root_dir + "/server/tools"
base.create_dir(tools_dir)
@ -150,13 +141,16 @@ 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'
#dictionaries
base.copy_dictionaries(server_dir + "/../dictionaries", root_dir + "/dictionaries")
spellchecker_dictionaries = root_dir + '/dictionaries'
spellchecker_dictionaries_files = server_dir + '/../dictionaries/*_*'
base.create_dir(spellchecker_dictionaries)
base.copy_files(spellchecker_dictionaries_files, spellchecker_dictionaries)
if (0 == platform.find("win")):
exec_ext = '.exe'
@ -189,7 +183,6 @@ 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'
@ -216,15 +209,15 @@ def make():
base.delete_dir(root_dir_snap)
base.create_dir(root_dir_snap)
base.copy_dir(root_dir, root_dir_snap)
base.copy_dir(server_dir + '/DocService/node_modules', root_dir_snap + '/server/DocService/node_modules')
base.copy_dir(server_dir + '/DocService/sources', root_dir_snap + '/server/DocService/sources')
base.copy_dir(server_dir + '/DocService/public', root_dir_snap + '/server/DocService/public')
base.copy_dir(bin_server_dir + '/DocService/node_modules', root_dir_snap + '/server/DocService/node_modules')
base.copy_dir(bin_server_dir + '/DocService/sources', root_dir_snap + '/server/DocService/sources')
base.copy_dir(bin_server_dir + '/DocService/public', root_dir_snap + '/server/DocService/public')
base.delete_file(root_dir_snap + '/server/DocService/docservice')
base.copy_dir(server_dir + '/FileConverter/node_modules', root_dir_snap + '/server/FileConverter/node_modules')
base.copy_dir(server_dir + '/FileConverter/sources', root_dir_snap + '/server/FileConverter/sources')
base.copy_dir(bin_server_dir + '/FileConverter/node_modules', root_dir_snap + '/server/FileConverter/node_modules')
base.copy_dir(bin_server_dir + '/FileConverter/sources', root_dir_snap + '/server/FileConverter/sources')
base.delete_file(root_dir_snap + '/server/FileConverter/converter')
base.copy_dir(server_dir + '/Common/node_modules', root_dir_snap + '/server/Common/node_modules')
base.copy_dir(server_dir + '/Common/sources', root_dir_snap + '/server/Common/sources')
base.copy_dir(bin_server_dir + '/Common/node_modules', root_dir_snap + '/server/Common/node_modules')
base.copy_dir(bin_server_dir + '/Common/sources', root_dir_snap + '/server/Common/sources')
if (base.is_dir(root_dir_snap_example)):
base.delete_dir(root_dir_snap_example)
base.create_dir(root_dir_snap_example)
@ -232,3 +225,4 @@ def make():
base.delete_file(root_dir_snap + '/example/nodejs/example')
return

View File

@ -5,6 +5,9 @@ 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()
@ -15,10 +18,16 @@ def make():
os.chdir(work_dir)
url = base.get_autobuild_version("core", "", config.option("branch"))
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"))
data_url = base.get_file_last_modified_url(url)
if (data_url == "" and config.option("branch") != "develop"):
url = base.get_autobuild_version("core", "", "develop")
url = get_core_url(arch, "develop")
data_url = base.get_file_last_modified_url(url)
old_data_url = base.readFile("./core.7z.data")
@ -40,25 +49,25 @@ 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("-----------------------------------------------------------")
print("Core is up to date. ---------------------------------------")
print("-----------------------------------------------------------")
base.generate_doctrenderer_config("./DoctRenderer.config", "../../../sdkjs/deploy/", "server", "../../../web-apps/vendor/", "../../../dictionaries")
base.generate_doctrenderer_config("./DoctRenderer.config", "../../../sdkjs/deploy/", "server", "../../../web-apps/vendor/")
if not base.is_dir(git_dir + "/sdkjs-plugins"):
base.create_dir(git_dir + "/sdkjs-plugins")
if not base.is_dir(git_dir + "/sdkjs-plugins/v1"):
base.create_dir(git_dir + "/sdkjs-plugins/v1")
base.download("https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.js", git_dir + "/sdkjs-plugins/v1/plugins.js")
base.download("https://onlyoffice.github.io/sdkjs-plugins/v1/plugins-ui.js", git_dir + "/sdkjs-plugins/v1/plugins-ui.js")
base.download("https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.css", git_dir + "/sdkjs-plugins/v1/plugins.css")
base.support_old_versions_plugins(git_dir + "/sdkjs-plugins")
base.copy_marketplace_plugin(git_dir + "/sdkjs-plugins", False, False)
base.clone_marketplace_plugin(git_dir + "/sdkjs-plugins", False, False, False)
if not base.is_dir(git_dir + "/fonts"):
base.create_dir(git_dir + "/fonts")
@ -92,8 +101,7 @@ def make():
server_addons = []
if (config.option("server-addons") != ""):
server_addons = config.option("server-addons").rsplit(", ")
#server-lockstorage is private
if ("server-lockstorage" in server_addons and base.is_dir(git_dir + "/server-lockstorage")):
if ("server-lockstorage" in server_addons):
server_config["editorDataStorage"] = "editorDataRedis"
sdkjs_addons = []
@ -117,8 +125,6 @@ def make():
sql["type"] = config.option("sql-type")
if (config.option("db-port") != ""):
sql["dbPort"] = config.option("db-port")
if (config.option("db-name") != ""):
sql["dbName"] = config.option("db-name")
if (config.option("db-user") != ""):
sql["dbUser"] = config.option("db-user")
if (config.option("db-pass") != ""):
@ -138,10 +144,8 @@ def make():
example_config["siteUrl"] = "http://" + config.option("siteUrl") + ":8000/"
example_config["apiUrl"] = "web-apps/apps/api/documents/api.js"
example_config["preloaderUrl"] = "web-apps/apps/api/documents/cache-scripts.html"
json_dir = git_dir + "/document-server-integration/web/documentserver-example/nodejs/config/"
json_file = json_dir + "/local-development-" + base.host_platform() + ".json"
if base.is_exist(json_dir):
base.writeFile(json_file, json.dumps({"server": example_config}, indent=2))
json_file = git_dir + "/document-server-integration/web/documentserver-example/nodejs/config/local-development-" + base.host_platform() + ".json"
base.writeFile(json_file, json.dumps({"server": example_config}, indent=2))
os.chdir(old_cur)
return

View File

@ -66,28 +66,6 @@ class CDependencies:
res += ['--remove-path', item]
return res
def check__docker_dependencies():
if (host_platform == 'windows' and not check_vc_components()):
return False
if (host_platform == 'mac'):
return True
checksResult = CDependencies()
checksResult.append(check_nodejs())
checksResult.append(check_7z())
if (len(checksResult.install) > 0):
install_args = ['install.py']
install_args += checksResult.get_uninstall()
install_args += checksResult.get_removepath()
install_args += checksResult.get_install()
base_dir = base.get_script_dir(__file__)
install_args[0] = './scripts/develop/' + install_args[0]
if (host_platform == 'windows'):
code = libwindows.sudo(unicode(sys.executable), install_args)
elif (host_platform == 'linux'):
get_updates()
base.cmd_in_dir(base_dir + "/../../", 'python', install_args, False)
def check_dependencies():
if (host_platform == 'windows' and not check_vc_components()):
return False
@ -190,21 +168,21 @@ def check_nodejs():
nodejs_cur_version_major = int(nodejs_version.split('.')[0][1:])
nodejs_cur_version_minor = int(nodejs_version.split('.')[1])
print('Installed Node.js version: ' + nodejs_version[1:])
nodejs_min_version = '18'
nodejs_min_version = '14.14'
nodejs_min_version_minor = 0
major_minor_min_version = nodejs_min_version.split('.')
nodejs_min_version_major = int(major_minor_min_version[0])
if len(major_minor_min_version) > 1:
nodejs_min_version_minor = int(major_minor_min_version[1])
nodejs_max_version = ""
nodejs_max_version = '18'
nodejs_max_version_minor = float("inf")
major_minor_max_version = nodejs_max_version.split('.')
# nodejs_max_version_major = int(major_minor_max_version[0])
nodejs_max_version_major = float("inf")
nodejs_max_version_major = int(major_minor_max_version[0])
if len(major_minor_max_version) > 1:
nodejs_max_version_minor = int(major_minor_max_version[1])
if (nodejs_min_version_major > nodejs_cur_version_major or nodejs_cur_version_major > nodejs_max_version_major):
print('Installed Node.js version must be 14.14 to 18.x')
isNeedReinstall = True
elif (nodejs_min_version_major == nodejs_cur_version_major):
if (nodejs_min_version_minor > nodejs_cur_version_minor):
@ -214,7 +192,7 @@ def check_nodejs():
isNeedReinstall = True
if (True == isNeedReinstall):
print('Installed Node.js version must be 18 or higher.')
print('Installed Node.js version must be 14.14 to 14.x')
if (host_platform == 'windows'):
dependence.append_uninstall('Node.js')
dependence.append_install('Node.js')
@ -483,8 +461,8 @@ def get_mysql_path_to_bin(mysqlPath = ''):
mysqlPath = os.environ['PROGRAMW6432'] + '\\MySQL\\MySQL Server 8.0\\'
mysqlPath += 'bin'
return mysqlPath
def get_mysqlLoginString():
return 'mysql -u ' + config.option("db-user") + ' -p' + config.option("db-pass")
def get_mysqlLoginSrting():
return 'mysql -u ' + install_params['MySQLServer']['user'] + ' -p' + install_params['MySQLServer']['pass']
def get_mysqlServersInfo():
arrInfo = []
@ -511,14 +489,14 @@ def get_mysqlServersInfo():
def check_mysqlServer():
base.print_info('Check MySQL Server')
dependence = CDependencies()
mysqlLoginSrt = get_mysqlLoginString()
mysqlLoginSrt = get_mysqlLoginSrting()
connectionString = mysqlLoginSrt + ' -e "SHOW GLOBAL VARIABLES LIKE ' + r"'PORT';" + '"'
if (host_platform != 'windows'):
result = os.system(mysqlLoginSrt + ' -e "exit"')
if (result == 0):
connectionResult = base.run_command(connectionString)['stdout']
if (connectionResult.find('port') != -1 and connectionResult.find(config.option("db-port")) != -1):
if (connectionResult.find('port') != -1 and connectionResult.find(install_params['MySQLServer']['port']) != -1):
print('MySQL configuration is valid')
dependence.sqlPath = 'mysql'
return dependence
@ -535,13 +513,11 @@ def check_mysqlServer():
mysql_full_name = 'MySQL Server ' + info['Version'] + ' '
connectionResult = base.run_command_in_dir(get_mysql_path_to_bin(info['Location']), connectionString)['stdout']
if (connectionResult.find('port') != -1 and connectionResult.find(config.option("db-port")) != -1):
if (connectionResult.find('port') != -1 and connectionResult.find(install_params['MySQLServer']['port']) != -1):
print(mysql_full_name + 'configuration is valid')
dependence.sqlPath = info['Location']
return dependence
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(mysql_full_name + 'configuration is not valid')
print('Valid MySQL Server not found')
dependence.append_uninstall('MySQL Server')
@ -561,43 +537,23 @@ def check_mysqlServer():
return dependence
def check_MySQLConfig(mysqlPath = ''):
result = True
mysqlLoginSrt = get_mysqlLoginString()
mysqlLoginSrt = get_mysqlLoginSrting()
mysql_path_to_bin = get_mysql_path_to_bin(mysqlPath)
if (base.run_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "SHOW DATABASES;"')['stdout'].lower().find(config.option("db-name").lower()) == -1):
print('Database "' + config.option("db-name") + '" not found')
result = create_MySQLDb(mysql_path_to_bin, config.option("db-name"), config.option("db-user"), config.option("db-pass"))
if (not result):
return False
print('Creating ' + config.option("db-name") + ' tables ...')
if (base.run_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "SHOW DATABASES;"')['stdout'].find('onlyoffice') == -1):
print('Database onlyoffice not found')
creatdb_path = base.get_script_dir() + "/../../server/schema/mysql/createdb.sql"
result = execMySQLScript(mysql_path_to_bin, config.option("db-name"), creatdb_path)
if (base.run_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "SELECT plugin from mysql.user where User=' + "'" + config.option("db-user") + "';" + '"')['stdout'].find('mysql_native_password') == -1):
result = execMySQLScript(mysql_path_to_bin, creatdb_path)
if (base.run_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "SELECT plugin from mysql.user where User=' + "'" + install_params['MySQLServer']['user'] + "';" + '"')['stdout'].find('mysql_native_password') == -1):
print('Password encryption is not valid')
result = set_MySQLEncrypt(mysql_path_to_bin, 'mysql_native_password') and result
return result
def create_MySQLDb(mysql_path_to_bin, dbName, dbUser, dbPass):
mysqlLoginSrt = get_mysqlLoginString()
print('CREATE DATABASE ' + dbName + ';')
if (base.exec_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "CREATE DATABASE ' + dbName + ';"') != 0):
print('failed CREATE DATABASE ' + dbName + ';')
return False
# print('CREATE USER IF NOT EXISTS ' + dbUser + ' IDENTIFIED BY \'' + dbPass + '\';')
# if (base.exec_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "CREATE USER IF NOT EXISTS ' + dbUser + ' IDENTIFIED BY \'' + dbPass + '\';"') != 0):
# print('failed: CREATE USER IF NOT EXISTS ' + dbUser + ' IDENTIFIED BY \'' + dbPass + '\';')
# return False
# print('GRANT ALL PRIVILEGES ON ' + dbName + '.* TO ' + dbUser + ';')
# if (base.exec_command_in_dir(mysql_path_to_bin, mysqlLoginSrt + ' -e "GRANT ALL PRIVILEGES ON ' + dbName + '.* TO ' + dbUser + ';"') != 0):
# print('failed: GRANT ALL PRIVILEGES ON ' + dbName + '.* TO ' + dbUser + ';')
# return False
return True
def execMySQLScript(mysql_path_to_bin, dbName, scriptPath):
def execMySQLScript(mysql_path_to_bin, scriptPath):
print('Execution ' + scriptPath)
mysqlLoginSrt = get_mysqlLoginString()
mysqlLoginSrt = get_mysqlLoginSrting()
code = base.exec_command_in_dir(mysql_path_to_bin, get_mysqlLoginString() + ' -D ' + dbName + ' < "' + scriptPath + '"')
code = base.exec_command_in_dir(mysql_path_to_bin, get_mysqlLoginSrting() + ' < "' + scriptPath + '"')
if (code != 0):
print('Execution failed!')
return False
@ -606,7 +562,7 @@ def execMySQLScript(mysql_path_to_bin, dbName, scriptPath):
def set_MySQLEncrypt(mysql_path_to_bin, sEncrypt):
print('Setting MySQL password encrypting...')
code = base.exec_command_in_dir(mysql_path_to_bin, get_mysqlLoginString() + ' -e "' + "ALTER USER '" + config.option("db-user") + "'@'localhost' IDENTIFIED WITH " + sEncrypt + " BY '" + config.option("db-pass") + "';" + '"')
code = base.exec_command_in_dir(mysql_path_to_bin, get_mysqlLoginSrting() + ' -e "' + "ALTER USER '" + install_params['MySQLServer']['user'] + "'@'localhost' IDENTIFIED WITH " + sEncrypt + " BY '" + install_params['MySQLServer']['pass'] + "';" + '"')
if (code != 0):
print('Setting password encryption failed!')
return False
@ -633,7 +589,7 @@ def get_postrgre_path_to_bin(postgrePath = ''):
def get_postgreLoginSrting(userName):
if (host_platform == 'windows'):
return 'psql -U' + userName + ' '
return 'PGPASSWORD="' + config.option("db-pass") + '" psql -U' + userName + ' -hlocalhost '
return 'PGPASSWORD="' + install_params['PostgreSQL']['dbPass'] + '" psql -U' + userName + ' -hlocalhost '
def get_postgreSQLInfoByFlag(flag):
arrInfo = []
@ -669,7 +625,7 @@ def check_postgreSQL():
result = os.system(postgreLoginSrt + ' -c "\q"')
connectionResult = base.run_command(connectionString)['stdout']
if (result != 0 or connectionResult.find(config.option("db-port")) == -1):
if (result != 0 or connectionResult.find(install_params['PostgreSQL']['dbPort']) == -1):
print('Valid PostgreSQL not found!')
dependence.append_install('PostgreSQL')
dependence.append_uninstall('PostgreSQL')
@ -679,7 +635,7 @@ def check_postgreSQL():
return dependence
arrInfo = get_postgreSQLInfo()
base.set_env('PGPASSWORD', config.option("db-pass"))
base.set_env('PGPASSWORD', install_params['PostgreSQL']['dbPass'])
for info in arrInfo:
if (base.is_dir(info['Location']) == False):
continue
@ -687,7 +643,7 @@ def check_postgreSQL():
postgre_full_name = 'PostgreSQL ' + info['Version'][:2] + ' '
connectionResult = base.run_command_in_dir(get_postrgre_path_to_bin(info['Location']), connectionString)['stdout']
if (connectionResult.find(config.option("db-port")) != -1):
if (connectionResult.find(install_params['PostgreSQL']['dbPort']) != -1):
print(postgre_full_name + 'configuration is valid')
dependence.sqlPath = info['Location']
return dependence
@ -705,12 +661,12 @@ def check_postgreSQL():
def check_postgreConfig(postgrePath = ''):
result = True
if (host_platform == 'windows'):
base.set_env('PGPASSWORD', config.option("db-pass"))
base.set_env('PGPASSWORD', install_params['PostgreSQL']['dbPass'])
rootUser = install_params['PostgreSQL']['root']
dbUser = config.option("db-user")
dbName = config.option("db-name")
dbPass = config.option("db-pass")
dbUser = install_params['PostgreSQL']['dbUser']
dbName = install_params['PostgreSQL']['dbName']
dbPass = install_params['PostgreSQL']['dbPass']
postgre_path_to_bin = get_postrgre_path_to_bin(postgrePath)
postgreLoginRoot = get_postgreLoginSrting(rootUser)
postgreLoginDbUser = get_postgreLoginSrting(dbUser)
@ -727,7 +683,7 @@ def check_postgreConfig(postgrePath = ''):
base.print_info('Creating ' + dbName + ' user...')
result = create_postgreUser(dbUser, dbPass, postgre_path_to_bin) and result
if (base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + ' -c "SELECT datname FROM pg_database;"')['stdout'].find(config.option("db-name")) == -1):
if (base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + ' -c "SELECT datname FROM pg_database;"')['stdout'].find('onlyoffice') == -1):
print('Database ' + dbName + ' not found')
base.print_info('Creating ' + dbName + ' database...')
result = create_postgreDb(dbName, postgre_path_to_bin) and configureDb(dbUser, dbName, creatdb_path, postgre_path_to_bin)
@ -906,13 +862,13 @@ def install_gruntcli():
def install_mysqlserver():
if (host_platform == 'windows'):
return os.system('"' + os.environ['ProgramFiles(x86)'] + '\\MySQL\\MySQL Installer for Windows\\MySQLInstallerConsole" community install server;' + install_params['MySQLServer']['version'] + ';x64:*:type=config;openfirewall=true;generallog=true;binlog=true;serverid=' + config.option("db-port") + 'enable_tcpip=true;port=' + config.option("db-port") + ';rootpasswd=' + config.option("db-pass") + ' -silent')
return os.system('"' + os.environ['ProgramFiles(x86)'] + '\\MySQL\\MySQL Installer for Windows\\MySQLInstallerConsole" community install server;' + install_params['MySQLServer']['version'] + ';x64:*:type=config;openfirewall=true;generallog=true;binlog=true;serverid=' + install_params['MySQLServer']['port'] + 'enable_tcpip=true;port=' + install_params['MySQLServer']['port'] + ';rootpasswd=' + install_params['MySQLServer']['pass'] + ' -silent')
elif (host_platform == 'linux'):
os.system('sudo kill ' + base.run_command('sudo fuser -vn tcp ' + config.option("db-port"))['stdout'])
os.system('sudo kill ' + base.run_command('sudo fuser -vn tcp ' + install_params['MySQLServer']['port'])['stdout'])
code = os.system('sudo ufw enable && sudo ufw allow 22 && sudo ufw allow 3306')
code = os.system('sudo apt-get -y install zsh htop') and code
code = os.system('echo "mysql-server mysql-server/root_password password ' + config.option("db-pass") + '" | sudo debconf-set-selections') and code
code = os.system('echo "mysql-server mysql-server/root_password_again password ' + config.option("db-pass") + '" | sudo debconf-set-selections') and code
code = os.system('echo "mysql-server mysql-server/root_password password ' + install_params['MySQLServer']['pass'] + '" | sudo debconf-set-selections') and code
code = os.system('echo "mysql-server mysql-server/root_password_again password ' + install_params['MySQLServer']['pass'] + '" | sudo debconf-set-selections') and code
return os.system('yes | sudo apt install mysql-server') and code
return 1
@ -934,7 +890,7 @@ def install_postgresql():
file_name = "install.exe"
base.download(download_url, file_name)
base.print_info("Install PostgreSQL...")
install_command = file_name + ' --mode unattended --unattendedmodeui none --superpassword ' + config.option("db-pass") + ' --serverport ' + config.option("db-port")
install_command = file_name + ' --mode unattended --unattendedmodeui none --superpassword ' + install_params['PostgreSQL']['dbPass'] + ' --serverport ' + install_params['PostgreSQL']['dbPort']
else:
base.print_info("Install PostgreSQL...")
install_command = 'sudo apt install postgresql -y'
@ -945,12 +901,12 @@ def install_postgresql():
if (host_platform == 'windows'):
base.delete_file(file_name)
else:
code = os.system('sudo -i -u postgres psql -c "ALTER USER postgres PASSWORD ' + "'" + config.option("db-pass") + "'" + ';"') and code
code = os.system('sudo -i -u postgres psql -c "ALTER USER postgres PASSWORD ' + "'" + install_params['PostgreSQL']['dbPass'] + "'" + ';"') and code
return code
def install_nodejs():
os.system('curl -sSL https://deb.nodesource.com/setup_18.x | sudo -E bash -')
os.system('curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -')
base.print_info("Install node.js...")
install_command = 'yes | sudo apt install nodejs'
print(install_command)
@ -959,7 +915,7 @@ def install_nodejs():
downloads_list = {
'Windows': {
'Git': 'https://github.com/git-for-windows/git/releases/download/v2.29.0.windows.1/Git-2.29.0-64-bit.exe',
'Node.js': 'https://nodejs.org/dist/v18.17.1/node-v18.17.1-x64.msi',
'Node.js': 'https://nodejs.org/download/release/v14.17.6/node-v14.17.6-x64.msi',
'Java': 'https://aka.ms/download-jdk/microsoft-jdk-11.0.18-windows-x64.msi',
'RabbitMQ': 'https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.9/rabbitmq-server-3.8.9.exe',
'Erlang': 'http://erlang.org/download/otp_win64_23.1.exe',
@ -996,11 +952,18 @@ install_params = {
'BuildTools': '--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --wait',
'Git': '/VERYSILENT /NORESTART',
'MySQLServer': {
'port': '3306',
'user': 'root',
'pass': 'onlyoffice',
'version': '8.0.21'
},
'Redis': 'PORT=6379 ADD_FIREWALL_RULE=1',
'PostgreSQL': {
'root': 'postgres'
'root': 'postgres',
'dbPort': '5432',
'dbName': 'onlyoffice',
'dbUser': 'onlyoffice',
'dbPass': 'onlyoffice'
}
}
uninstall_params = {

View File

@ -10,15 +10,11 @@ import config_server as develop_config_server
base_dir = base.get_script_dir(__file__)
def build_docker_server():
dependence.check__docker_dependencies()
build_develop_server()
def build_docker_sdk_web_apps(dir):
dependence.check__docker_dependencies()
build_js.build_js_develop(dir)
def build_develop_server():
def make():
if ("1" != config.option("develop")):
return
if not dependence.check_dependencies():
exit(1)
build_server.build_server_develop()
build_js.build_js_develop(base_dir + "/../../..")
develop_config_server.make()
@ -26,12 +22,5 @@ def build_develop_server():
branding_develop_script_dir = base_dir + "/../../../" + config.option("branding") + "/build_tools/scripts"
if base.is_file(branding_develop_script_dir + "/develop.py"):
base.cmd_in_dir(branding_develop_script_dir, "python", ["develop.py"], True)
def make():
if ("1" != config.option("develop")):
return
if not dependence.check_dependencies():
exit(1)
build_develop_server()
exit(0)

View File

@ -1,342 +0,0 @@
#!/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()

View File

@ -6,7 +6,6 @@ import base
import shutil
import optparse
import dependence
import config
arguments = sys.argv[1:]
@ -18,10 +17,6 @@ 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"]:

View File

@ -35,8 +35,12 @@ config.parse_defaults()
repositories = base.get_repositories()
# Add other repositories
if (config.check_option("module", "desktop")):
repositories['appimage-desktopeditors'] = [False, False]
if config.check_option("module", "builder"):
repositories['document-builder-package'] = [False, False]
repositories['appimage-documentbuilder'] = [False, False]
if (config.check_option("module", "server")):
repositories['document-server-package'] = [False, False]

View File

@ -6,9 +6,6 @@ import os
import base
import dependence
import traceback
import develop
base_dir = base.get_script_dir(__file__)
def install_module(path):
base.print_info('Install: ' + path)
@ -44,98 +41,56 @@ def start_linux_services():
os.system('sudo service rabbitmq-server restart')
def run_integration_example():
if base.is_exist(base_dir + '/../../../document-server-integration/web/documentserver-example/nodejs'):
base.cmd_in_dir(base_dir + '/../../../document-server-integration/web/documentserver-example/nodejs', 'python', ['run-develop.py'])
base.cmd_in_dir('../../../document-server-integration/web/documentserver-example/nodejs', 'python', ['run-develop.py'])
def start_linux_services():
base.print_info('Restart MySQL Server')
def update_config(args):
platform = base.host_platform()
branch = base.run_command('git rev-parse --abbrev-ref HEAD')['stdout']
if ("linux" == platform):
base.cmd_in_dir(base_dir + '/../../', 'python', ['configure.py', '--branch', branch or 'develop', '--develop', '1', '--module', 'server', '--update', '1', '--update-light', '1', '--clean', '0'] + args)
else:
base.cmd_in_dir(base_dir + '/../../', 'python', ['configure.py', '--branch', branch or 'develop', '--develop', '1', '--module', 'server', '--update', '1', '--update-light', '1', '--clean', '0', '--sql-type', 'mysql', '--db-port', '3306', '--db-name', 'onlyoffice', '--db-user', 'root', '--db-pass', 'onlyoffice'] + args)
def make_start():
base.configure_common_apps()
platform = base.host_platform()
if ("windows" == platform):
dependence.check_pythonPath()
dependence.check_gitPath()
restart_win_rabbit()
elif ("mac" == platform):
start_mac_services()
elif ("linux" == platform):
start_linux_services()
def make_configure(args):
base.print_info('Build modules')
update_config(args)
base.cmd_in_dir(base_dir + '/../../', 'python', ['make.py'])
def make_install():
platform = base.host_platform()
run_integration_example()
base.create_dir(base_dir + '/../../../server/App_Data')
install_module(base_dir + '/../../../server/DocService')
install_module(base_dir + '/../../../server/Common')
install_module(base_dir + '/../../../server/FileConverter')
def make_run():
platform = base.host_platform()
base.set_env('NODE_ENV', 'development-' + platform)
base.set_env('NODE_CONFIG_DIR', '../Common/config')
if ("mac" == platform):
base.set_env('DYLD_LIBRARY_PATH', '../FileConverter/bin/')
elif ("linux" == platform):
base.set_env('LD_LIBRARY_PATH', '../FileConverter/bin/')
run_module(base_dir + '/../../../server/DocService', ['sources/server.js'])
#run_module(base_dir + '/../../../server/DocService', ['sources/gc.js'])
run_module(base_dir + '/../../../server/FileConverter', ['sources/convertermaster.js'])
#run_module(base_dir + '/../../../server/SpellChecker', ['sources/server.js'])
def run_docker_server(args = []):
try:
make_start()
develop.build_docker_server()
make_install()
except SystemExit:
input("Ignoring SystemExit. Press Enter to continue...")
exit(0)
except KeyboardInterrupt:
pass
except:
input("Unexpected error. " + traceback.format_exc() + "Press Enter to continue...")
def run_docker_sdk_web_apps(dir):
try:
develop.build_docker_sdk_web_apps(dir)
except SystemExit:
input("Ignoring SystemExit. Press Enter to continue...")
exit(0)
except KeyboardInterrupt:
pass
except:
input("Unexpected error. " + traceback.format_exc() + "Press Enter to continue...")
def make(args = []):
try:
make_start()
make_configure(args)
make_install()
make_run()
base.configure_common_apps()
platform = base.host_platform()
if ("windows" == platform):
dependence.check_pythonPath()
dependence.check_gitPath()
restart_win_rabbit()
elif ("mac" == platform):
start_mac_services()
elif ("linux" == platform):
start_linux_services()
branch = base.run_command('git rev-parse --abbrev-ref HEAD')['stdout']
base.print_info('Build modules')
if ("linux" == platform):
base.cmd_in_dir('../../', 'python', ['configure.py', '--branch', branch or 'develop', '--develop', '1', '--module', 'server', '--update', '1', '--update-light', '1', '--clean', '0'] + args)
else:
base.cmd_in_dir('../../', 'python', ['configure.py', '--branch', branch or 'develop', '--develop', '1', '--module', 'server', '--update', '1', '--update-light', '1', '--clean', '0', '--sql-type', 'mysql', '--db-port', '3306', '--db-user', 'root', '--db-pass', 'onlyoffice'] + args)
base.cmd_in_dir('../../', 'python', ['make.py'])
run_integration_example()
base.create_dir('../../../server/App_Data')
install_module('../../../server/DocService')
install_module('../../../server/Common')
install_module('../../../server/FileConverter')
base.set_env('NODE_ENV', 'development-' + platform)
base.set_env('NODE_CONFIG_DIR', '../Common/config')
if ("mac" == platform):
base.set_env('DYLD_LIBRARY_PATH', '../FileConverter/bin/')
elif ("linux" == platform):
base.set_env('LD_LIBRARY_PATH', '../FileConverter/bin/')
run_module('../../../server/DocService', ['sources/server.js'])
# run_module('../../../server/DocService', ['sources/gc.js'])
run_module('../../../server/FileConverter', ['sources/convertermaster.js'])
# run_module('../../../server/SpellChecker', ['sources/server.js'])
except SystemExit:
input("Ignoring SystemExit. Press Enter to continue...")
exit(0)

View File

@ -56,6 +56,13 @@ save text files with reports.
"reportFolder": "build_tools/scripts/license_checker/reports"
```
* `licensePath` specifies the path to the license template.
**For example:**
```json
"licensePath": "build_tools/scripts/license_checker/license_template.txt"
```
* `printChecking` specifies whether to output
information about which file is
being checked to the console.
@ -103,14 +110,36 @@ Possible array values:
```json
"fileExtensions": [".js"]
```
* `licensePath` specifies the path to the license template.
* `startMultiComm` the line that starts the multiline comment.
**For example:**
```json
"licensePath": "header.license"
"startMultiComm": "/*"
```
* `endMultiComm` the line that ends the multiline comment.
You should carefully consider the formatting
of the string, all spaces are taken into account.
This affects how the license check works.
**For example:**
```json
"endMultiComm": " */"
```
Space at the beginning for a prettier comment.
* `prefix` the line on which each comment
line will begin, except for the
beginning and end.
**For example:**
```json
"prefix": " *"
```
Space at the beginning for a prettier comment.
* `ignoreListDir` folder paths to ignore.
**For example:**
@ -143,18 +172,6 @@ Possible array values:
]
```
* `allowListFile` file paths to allow. It is needed if you ignore the directory, but there is a file in it that needs to be checked.
**For example:**
```json
"ignoreListDir": [
"sdkjs/develop"
],
"allowListFile": [
"sdkjs/develop/awesomeFileToAllow.js",
]
```
Any number of configurations can be
specified, they can overlap
if we need to check

View File

@ -1,6 +1,7 @@
{
"basePath": "../../../",
"reportFolder": "build_tools/scripts/license_checker/reports",
"licensePath": "build_tools/scripts/license_checker/header.license",
"printChecking": false,
"printReports": false,
"fix": ["OUTDATED"],
@ -8,7 +9,9 @@
{
"dir": "core",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".cs", ".js", ".m", ".mm", ".license"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"core/build",
"core/Common/cfcpp/test",
@ -21,15 +24,14 @@
"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/Apple",
"core/HwpFile",
"core/HtmlFile2",
"core/OdfFile/Common/utf8cpp",
"core/OfficeUtils/js/emsdk",
"core/OfficeUtils/src/zlib-1.2.11",
@ -57,7 +59,9 @@
{
"dir": "core-ext",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".m", ".mm"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"core-ext/AutoTester",
"core-ext/cell_android",
@ -79,7 +83,9 @@
{
"dir": "sdkjs",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"sdkjs/deploy",
"sdkjs/develop",
@ -100,7 +106,9 @@
{
"dir": "sdkjs-forms",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -109,7 +117,9 @@
{
"dir": "sdkjs-ooxml",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -118,7 +128,9 @@
{
"dir": "web-apps",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor",
@ -126,7 +138,6 @@
],
"ignoreListDir": [
"web-apps/apps/common/mobile",
"web-apps/apps/common/main/lib/mods",
"web-apps/apps/documenteditor/mobile",
"web-apps/apps/spreadsheeteditor/mobile",
"web-apps/apps/presentationeditor/mobile",
@ -134,6 +145,7 @@
],
"ignoreListFile": [
"web-apps/apps/api/documents/api.js",
"web-apps/apps/common/main/lib/mods/perfect-scrollbar.js",
"web-apps/apps/common/main/lib/core/application.js",
"web-apps/apps/common/main/lib/core/keymaster.js",
"web-apps/apps/presentationeditor/embed/resources/less/watch.js"
@ -142,7 +154,9 @@
{
"dir": "web-apps-mobile",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -151,7 +165,9 @@
{
"dir": "server",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
@ -162,7 +178,12 @@
{
"dir": "server-lockstorage",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
"ignoreListDirName": [
"node_modules"
]
@ -170,15 +191,12 @@
{
"dir": "server-license",
"fileExtensions": [".js"],
"licensePath": "header.license",
"ignoreListDirName": [
"node_modules"
]
},
{
"dir": "server-license-key",
"fileExtensions": [".js"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
"ignoreListDirName": [
"node_modules"
]
@ -186,7 +204,9 @@
{
"dir": "editors-ios",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".m", ".mm"],
"licensePath": "header.license",
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"vendor",
"Vendor",

View File

@ -1,31 +1,28 @@
/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* 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)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
(c) Copyright Ascensio System SIA 2010-2023
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)
version 3 as published by the Free Software Foundation. In accordance with
Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
that Ascensio System SIA expressly excludes the warranty of non-infringement
of any third-party rights.
This program is distributed WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
street, Riga, Latvia, EU, LV-1050.
The interactive user interfaces in modified source and object code versions
of the Program must display Appropriate Legal Notices, as required under
Section 5 of the GNU AGPL version 3.
Pursuant to Section 7(b) of the License you must retain the original Product
logo when distributing the program. Pursuant to Section 7(e) we decline to
grant you any rights under trademark law for use of our trademarks.
All the Product's GUI elements, including illustrations and icon sets, as
well as technical writing content are licensed under the terms of the
Creative Commons Attribution-ShareAlike 4.0 International. See the License
terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode

View File

@ -25,6 +25,9 @@ class Config(object):
Attributes:
dir: Directory to check.
fileExtensions: file extensions to check.
startMultiComm: characters to start a multi-line comment.
endMultiComm: characters to end a multi-line comment.
prefix: prefix for multiline comments
ignoreListDir: Ignored folder paths.
ignoreListDirName: Ignored folder names.
ignoreListFile: Ignored file paths.
@ -33,7 +36,9 @@ class Config(object):
def __init__(self,
dir: str,
fileExtensions: list[str],
licensePath: str = 'header.license',
startMultiComm: str,
endMultiComm: str,
prefix: str = '',
allowListFile: list[str] = [],
ignoreListDir: list[str] = [],
ignoreListDirName: list[str] = [],
@ -41,19 +46,13 @@ class Config(object):
self._dir = dir
self._fileExtensions = fileExtensions
self._startMultiComm = startMultiComm
self._endMultiComm = endMultiComm
self._prefix = prefix
self._allowListFile = allowListFile
self._ignoreListDir = ignoreListDir
self._ignoreListDirName = ignoreListDirName
self._ignoreListFile = ignoreListFile
"""Read license template."""
with open(licensePath, 'r', encoding="utf8") as file:
lines = file.readlines()
if not lines:
raise Exception(f'Error getting license template. Cannot read {licensePath} file. Is not it empty?')
non_empty_lines = [s for s in lines if not s.isspace()]
self._startMultiComm = non_empty_lines[0]
self._endMultiComm = non_empty_lines[-1]
self._license_lines = lines
def getDir(self) -> str:
return self._dir
@ -63,8 +62,8 @@ class Config(object):
return self._startMultiComm
def getEndMultiComm(self) -> str:
return self._endMultiComm
def getLicense(self) -> list[str]:
return self._license_lines
def getPrefix(self) -> str:
return self._prefix
def getAllowListFile(self) -> list[str]:
return self._allowListFile
def getIgnoreListDir(self) -> list[str]:
@ -78,6 +77,7 @@ with open(CONFIG_PATH, 'r') as j:
_json: dict = json.load(j)
BASE_PATH: str = _json.get('basePath') or '../../../'
REPORT_FOLDER: str = _json.get('reportFolder') or 'build_tools/scripts/license_checker/reports'
LICENSE_TEMPLATE_PATH: str = _json.get('licensePath') or 'build_tools/scripts/license_checker/header.license'
if (_json.get('fix')):
try:
FIX: list[ErrorType] = list(map(lambda x: FIX_TYPES[x], _json.get('fix')))
@ -93,6 +93,23 @@ with open(CONFIG_PATH, 'r') as j:
os.chdir(BASE_PATH)
with open(LICENSE_TEMPLATE_PATH, 'r') as f:
LICENSE: list[str] = f.readlines()
if not LICENSE:
raise Exception(f'Error getting license template. Cannot read {LICENSE_TEMPLATE_PATH} file. Is not it empty?')
def getLicense(start: str, prefix: str, end: str) -> list[str]:
"""Returns a valid license for any kind of comment prefix."""
result = [start]
for i in LICENSE:
if i == '\n':
result.append(prefix)
else:
result.append(f'{" ".join([prefix, i.strip()])}')
result.append(prefix)
result.append(end)
return result
class Error(object):
def __init__(self, errorType: ErrorType) -> None:
self._errorType = errorType
@ -127,6 +144,8 @@ class Checker(object):
self._reports: list[Report] = []
def getReports(self):
return self._reports
def getLicense(self):
return getLicense(start=self._config.getStartMultiComm(), prefix=self._config.getPrefix(), end=self._config.getEndMultiComm())
def _checkLine(self, line: str, prefix: str) -> bool:
"""Checks if a line has a prefix."""
"""Trim to catch invalid license without leading spaces"""
@ -153,7 +172,7 @@ class Checker(object):
break
return result
def _checkLicense(self, test: list[str], pathToFile: str) -> Report:
license = self._config.getLicense()
license = self.getLicense()
if len(license) != len(test):
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.LEN_MISMATCH),
@ -161,29 +180,32 @@ class Checker(object):
invalidLinesCount = 0
lastWrongLine = 0
for i in range(len(license)):
if (license[i] != test[i]):
if (license[i] != test[i].strip('\n')):
invalidLinesCount += 1
lastWrongLine = i
if (invalidLinesCount == 1):
r = r'\d\d\d\d'
testDate = re.findall(r, test[lastWrongLine])
licenseDate = re.findall(r, license[lastWrongLine])
r = r'\d\d\d\d\-\d\d\d\d'
testDate = re.search(r, test[lastWrongLine])
licenseDate = re.search(r, license[lastWrongLine])
if not (testDate and licenseDate):
if testDate and licenseDate:
testDate = testDate.group()
licenseDate = licenseDate.group()
else:
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.INVALID_LICENSE),
message=f'Something wrong...')
testLastYear = int(testDate[-1])
licenseLastYear = int(licenseDate[-1])
if (testLastYear < licenseLastYear):
testLastYear = testDate.split('-')[1]
licenseLastYear = licenseDate.split('-')[1]
if (int(testLastYear) < int(licenseLastYear)):
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.OUTDATED),
message=f'Found date {testLastYear}, expected {licenseLastYear}')
message=f'Found date {testDate}, expected {licenseDate}')
else:
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.INVALID_LICENSE),
message=f"Found something similar to the date: {testLastYear}, but it's not correct. Expected: {licenseLastYear}")
message=f"Found something similar to the date: {testDate}, but it's not correct. Expected: {licenseDate}")
elif (invalidLinesCount > 0):
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.INVALID_LICENSE),
@ -264,9 +286,8 @@ class Fixer(object):
with open(pathToFile, 'r', encoding="utf8") as file:
buffer = file.readlines()
with open(pathToFile, 'w', encoding="utf8") as file:
license = self._config.getLicense()
file.writelines(license)
file.write('\n')
license = self._checker.getLicense()
file.writelines(map(lambda x: "".join([x, '\n']), license))
file.writelines(buffer)
return
def _fixLicense(self, pathToFile: str):
@ -280,8 +301,8 @@ class Fixer(object):
for i in oldLicense:
buffer.remove(i)
with open(pathToFile, 'w', encoding=writeEncoding) as file:
license = self._config.getLicense()
file.writelines(license)
license = self._checker.getLicense()
file.writelines(map(lambda x: "".join([x, '\n']), license))
file.writelines(buffer)
return
@ -307,7 +328,7 @@ def writeReports(reports: list[Report]) -> None:
for i in reports:
files[i.getError().getErrorType().name].append(i)
for i in ErrorType:
with open(f'{REPORT_FOLDER}/{i.name}.txt', 'w', encoding="utf8") as f:
with open(f'{REPORT_FOLDER}/{i.name}.txt', 'w') as f:
f.writelines(map(lambda x: "".join([x.report(), '\n']), files.get(i.name)))
for config in CONFIGS:

View File

@ -1,32 +0,0 @@
#!/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)

View File

@ -17,7 +17,10 @@ if utils.is_windows():
desktop_product_name = "Desktop Editors"
desktop_product_name_s = desktop_product_name.replace(" ","")
desktop_package_name = company_name + "-" + desktop_product_name_s
desktop_vcredist_list = ["2022"]
desktop_changes_dir = "desktop-apps/win-linux/package/windows/update/changes"
desktop_changes_url = "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/changes"
desktop_updates_url = "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/updates"
if utils.is_macos():
desktop_package_name = "ONLYOFFICE"
@ -30,42 +33,6 @@ if utils.is_macos():
builder_product_name = "Document Builder"
if utils.is_linux():
desktop_make_targets = [
{
"make": "tar",
"src": "tar/*.tar*",
"dst": "desktop/linux/generic/"
},
{
"make": "deb",
"src": "deb/*.deb",
"dst": "desktop/linux/debian/"
},
{
"make": "rpm",
"src": "rpm/build/RPMS/*/*.rpm",
"dst": "desktop/linux/rhel/"
},
{
"make": "rpm-suse",
"src": "rpm-suse/build/RPMS/*/*.rpm",
"dst": "desktop/linux/suse/"
}
]
server_make_targets = [
{
"make": "deb",
"src": "deb/*.deb",
"dst": "server/linux/debian/"
},
{
"make": "rpm",
"src": "rpm/builddir/RPMS/*/*.rpm",
"dst": "server/linux/rhel/"
},
{
"make": "tar",
"src": "*.tar*",
"dst": "server/linux/snap/"
}
]
desktop_make_targets = ["deb", "rpm", "suse-rpm", "tar"]
builder_make_targets = ["deb", "rpm"] # tar
server_make_targets = ["deb", "rpm", "tar"]

View File

@ -7,223 +7,217 @@ 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_linux()
make_macos()
elif utils.is_linux():
make_macos_linux()
make_linux()
else:
utils.log("Unsupported host OS")
return
def s3_upload(files, dst):
if not files: return False
def aws_s3_upload(files, key, ptype=None):
if not files:
return False
ret = True
for f in files:
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
if upload:
utils.log("URL: " + branding.s3_base_url + "/" + key)
key = "builder/" + key
for file in files:
if not utils.is_file(file):
utils.log_err("file not exist: " + file)
ret &= False
continue
args = ["aws"]
if hasattr(branding, "s3_endpoint_url"):
args += ["--endpoint-url=" + branding.s3_endpoint_url]
args += [
"s3", "cp", "--no-progress", "--acl", "public-read",
"--metadata", "md5=" + utils.get_md5(file),
file, "s3://" + branding.s3_bucket + "/" + key
]
if common.os_family == "windows":
upload = utils.cmd(*args, verbose=True)
else:
upload = utils.sh(" ".join(args), verbose=True)
ret &= upload
if upload and ptype is not None:
full_key = key
if full_key.endswith("/"): full_key += utils.get_basename(file)
utils.add_deploy_data("builder", ptype, file, full_key)
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 package_version, arch
global inno_file, zip_file, suffix, key_prefix
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
arch = {
suffix = {
"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")
if make_prepare():
make_zip()
make_wheel()
else:
utils.set_summary("builder zip build", False)
utils.set_summary("builder python wheel build", False)
utils.log_h2("copy arifacts")
utils.create_dir("build\\app")
utils.copy_dir_content(source_dir, "build\\app\\")
make_zip()
make_inno()
utils.set_cwd(common.workspace_dir)
return
def make_prepare():
args = [
"-Version", package_version,
"-Arch", arch
]
if common.sign:
args += ["-Sign"]
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.log_h3(zip_file)
ret = utils.cmd("7z", "a", "-y", zip_file, ".\\app\\*",
chdir="build", creates="build\\" + zip_file, verbose=True)
utils.set_summary("builder zip build", ret)
if common.deploy and ret:
utils.log_h2("builder zip deploy")
ret = s3_upload(utils.glob_path("zip/*.zip"), "builder/win/generic/")
ret = aws_s3_upload(["build\\" + zip_file], "win/generic/", "Portable")
utils.set_summary("builder zip deploy", ret)
return
def make_macos_linux():
utils.set_cwd("document-builder-package")
def make_inno():
utils.log_h2("builder inno build")
utils.log_h3(inno_file)
make_tar()
make_wheel()
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 = aws_s3_upload(["build\\" + inno_file], "win/inno/", "Installer")
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 = aws_s3_upload([builder_tar], "mac/", "Portable")
utils.set_summary("builder deploy", ret)
utils.set_cwd(common.workspace_dir)
return
def make_tar():
utils.log_h2("builder tar build")
make_args = ["tar"]
if common.platform == "darwin_arm64":
make_args += ["-e", "UNAME_M=arm64"]
def make_linux():
utils.set_cwd("document-builder-package")
utils.log_h2("builder build")
make_args = branding.builder_make_targets
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 tar build", ret)
utils.set_summary("builder build", ret)
rpm_arch = "x86_64"
if common.platform == "linux_aarch64": rpm_arch = "aarch64"
if common.deploy:
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)
utils.log_h2("builder deploy")
if ret:
if "tar" in branding.builder_make_targets:
utils.log_h2("builder tar deploy")
ret = aws_s3_upload(
utils.glob_path("tar/*.tar.gz"),
"linux/generic/", "Portable"
)
utils.set_summary("builder tar deploy", ret)
if "deb" in branding.builder_make_targets:
utils.log_h2("builder deb deploy")
ret = aws_s3_upload(
utils.glob_path("deb/*.deb"),
"linux/debian/", "Debian"
)
utils.set_summary("builder deb deploy", ret)
if "rpm" in branding.builder_make_targets:
utils.log_h2("builder rpm deploy")
ret = aws_s3_upload(
utils.glob_path("rpm/builddir/RPMS/" + rpm_arch + "/*.rpm"),
"linux/rhel/", "CentOS"
)
utils.set_summary("builder rpm deploy", ret)
else:
if "tar" in branding.builder_make_targets:
utils.set_summary("builder tar deploy", False)
if "deb" in branding.builder_make_targets:
utils.set_summary("builder deb deploy", False)
if "rpm" in branding.builder_make_targets:
utils.set_summary("builder rpm deploy", False)
utils.set_cwd(common.workspace_dir)
make_appimage()
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"
}
def make_appimage():
if not onlyoffice:
return
if not utils.is_file("document-builder-package/deb/onlyoffice-documentbuilder_%s-%s_amd64.deb" % (common.version, common.build))
return
if not common.platform in platform_tags: return
utils.set_cwd("appimage-documentbuilder")
utils.log_h2("builder python wheel build")
rc = utils.sh("make clean", verbose=True)
common.summary["builder appimage clean"] = rc
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)
# args = []
# if common.platform == "linux_aarch64":
# args += ["-e", "UNAME_M=aarch64"]
rc = utils.sh("make testing", verbose=True)
common.summary["builder appimage build"] = rc
utils.set_cwd(common.workspace_dir)
return

View File

@ -1,5 +1,19 @@
#!/usr/bin/env python
platformTitles = {
"windows_x64": "Windows x64",
"windows_x86": "Windows x86",
"windows_x64_xp": "Windows x64 XP",
"windows_x86_xp": "Windows x86 XP",
"darwin_x86_64": "macOS x86_64",
"darwin_arm64": "macOS arm64",
"darwin_x86_64_v8": "macOS x86_64 V8",
"linux_x86_64": "Linux x86_64",
"linux_aarch64": "Linux aarch64",
"linux_x86_64_cef": "Linux x86_64 cef107",
"android": "Android",
}
platformPrefixes = {
"windows_x64": "win_64",
"windows_x86": "win_32",
@ -15,3 +29,35 @@ platformPrefixes = {
out_dir = "build_tools/out"
tsa_server = "http://timestamp.digicert.com"
vcredist_links = {
"2022": {
"x64": {
"url": "https://aka.ms/vs/17/release/vc_redist.x64.exe",
"md5": "077f0abdc2a3881d5c6c774af821f787"
},
"x86": {
"url": "https://aka.ms/vs/17/release/vc_redist.x86.exe",
"md5": "ae427c1329c3b211a6d09f8d9506eb74"
}
},
"2015": {
"x64": {
"url": "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe",
"md5": "27b141aacc2777a82bb3fa9f6e5e5c1c"
},
"x86": {
"url": "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe",
"md5": "1a15e6606bac9647e7ad3caa543377cf"
}
},
"2013": {
"x64": {
"url": "https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe",
"md5": "96b61b8e069832e6b809f24ea74567ba"
},
"x86": {
"url": "https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe",
"md5": "0fc525b6b7b96a87523daa7a0013c69d"
}
}
}

View File

@ -10,84 +10,92 @@ def make():
utils.log("Unsupported host OS")
return
if common.deploy:
make_archive()
make_core()
return
def make_archive():
utils.set_cwd(utils.get_path(
"build_tools/out/" + common.prefix + "/" + branding.company_name.lower()))
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"])
utils.log_h2("core archive build")
utils.delete_file("core.7z")
args = ["7z", "a", "-y", "core.7z", "./core/*"]
if utils.is_windows():
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 deploy")
args = ["aws", "s3", "cp", "--acl", "public-read", "--no-progress",
"--metadata", "md5=" + utils.get_md5(core_7z),
core_7z, "s3://" + branding.s3_bucket + "/" + dest_version + "core.7z"]
if common.os_family == "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 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)
utils.set_summary("core 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.add_deploy_data("core", "Archive", core_7z, dest_version + "core.7z")
args = ["aws", "s3", "sync", "--delete",
"--acl", "public-read", "--no-progress",
"s3://" + branding.s3_bucket + "/" + dest_version,
"s3://" + branding.s3_bucket + "/" + dest_latest]
if common.os_family == "windows":
ret &= utils.cmd(*args, verbose=True)
else:
ret &= utils.sh(" ".join(args), verbose=True)
utils.set_summary("core deploy", ret)
return
def deploy_closure_maps(license):
if not common.deploy: return
utils.log_h1("CLOSURE MAPS")
utils.set_cwd(utils.get_path("sdkjs/build/maps"))
branch = utils.get_env("BRANCH_NAME")
maps = utils.glob_path("*.js.map")
if branch is None:
utils.log_err("BRANCH_NAME variable is undefined")
utils.set_summary("closure maps " + license + " deploy", False)
return
if not maps:
utils.log_err("files do not exist")
utils.set_summary("closure maps " + license + " deploy", False)
return
utils.log_h2("closure maps " + license + " deploy")
dest = "closure-maps/%s/%s/%s" % (common.version, common.build, license)
ret = True
for file in maps:
args = ["aws"]
if hasattr(branding, "s3_endpoint_url"):
args += ["--endpoint-url=" + branding.s3_endpoint_url]
args += [
"s3", "cp", "--no-progress", "--metadata", "md5=" + utils.get_md5(file),
file, "s3://" + branding.s3_bucket + "/" + dest + "/"
]
if common.os_family == "windows":
upload = utils.cmd(*args, verbose=True)
else:
upload = utils.sh(" ".join(args), verbose=True)
ret &= upload
if upload:
utils.add_deploy_data("core", "Closure maps " + license, file, dest + "/" + file)
utils.set_summary("closure maps " + license + " deploy", ret)
utils.set_cwd(common.workspace_dir)
return
def deploy_closuremaps_sdkjs(license):
if not common.deploy: return
utils.log_h1("SDKJS CLOSURE MAPS")
maps = utils.glob_path("sdkjs/build/maps/*.js.map")
if maps:
for m in maps: utils.log("- " + m)
else:
utils.log_err("files do not exist")
utils.set_summary("sdkjs closure maps %s deploy" % license, False)
return
utils.log_h2("sdkjs closure maps %s deploy" % license)
ret = True
for f in maps:
base = utils.get_basename(f)
key = "closure-maps/sdkjs/%s/%s/%s/%s" % (license, common.version, common.build, base)
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
ret &= upload
if upload:
utils.log("URL: " + branding.s3_base_url + "/" + key)
utils.set_summary("sdkjs closure maps %s deploy" % license, ret)
return
def deploy_closuremaps_webapps(license):
if not common.deploy: return
utils.log_h1("WEB-APPS CLOSURE MAPS")
maps = utils.glob_path("web-apps/deploy/web-apps/apps/*/*/*.js.map") \
+ utils.glob_path("web-apps/deploy/web-apps/apps/*/mobile/dist/js/*.js.map")
if maps:
for m in maps: utils.log("- " + m)
else:
utils.log_err("files do not exist")
utils.set_summary("web-apps closure maps %s deploy" % license, False)
return
utils.log_h2("web-apps closure maps %s deploy" % license)
ret = True
for f in maps:
base = utils.get_relpath(f, "web-apps/deploy/web-apps/apps").replace("/", "_")
key = "closure-maps/web-apps/%s/%s/%s/%s" % (license, common.version, common.build, base)
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
ret &= upload
if upload:
utils.log("URL: " + branding.s3_base_url + "/" + key)
utils.set_summary("web-apps closure maps %s deploy" % license, ret)
return

View File

@ -2,10 +2,10 @@
# -*- coding: utf-8 -*-
import os
import re
import package_utils as utils
import package_common as common
import package_branding as branding
import config
def make():
utils.log_h1("DESKTOP")
@ -19,15 +19,33 @@ def make():
utils.log("Unsupported host OS")
return
def s3_upload(files, dst):
if not files: return False
def aws_s3_upload(files, key, ptype=None):
if not files:
return False
ret = True
for f in files:
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
if upload:
utils.log("URL: " + branding.s3_base_url + "/" + key)
key = "desktop/" + key
for file in files:
if not utils.is_file(file):
utils.log_err("file not exist: " + file)
ret &= False
continue
args = ["aws"]
if hasattr(branding, "s3_endpoint_url"):
args += ["--endpoint-url=" + branding.s3_endpoint_url]
args += [
"s3", "cp", "--no-progress", "--acl", "public-read",
"--metadata", "md5=" + utils.get_md5(file),
file, "s3://" + branding.s3_bucket + "/" + key
]
if common.os_family == "windows":
upload = utils.cmd(*args, verbose=True)
else:
upload = utils.sh(" ".join(args), verbose=True)
ret &= upload
if upload and ptype is not None:
full_key = key
if full_key.endswith("/"): full_key += utils.get_basename(file)
utils.add_deploy_data("desktop", ptype, file, full_key)
return ret
#
@ -35,165 +53,308 @@ def s3_upload(files, dst):
#
def make_windows():
global package_name, package_version, arch, xp, suffix
global package_version, arch_list, source_dir, desktop_dir, viewer_dir, \
inno_file, inno_help_file, inno_sa_file, inno_update_file, advinst_file, zip_file
utils.set_cwd("desktop-apps\\win-linux\\package\\windows")
package_name = branding.desktop_package_name
package_version = common.version + "." + common.build
arch = {
arch_list = {
"windows_x64": "x64",
"windows_x64_xp": "x64",
"windows_x86": "x86",
"windows_x86_xp": "x86"
}[common.platform]
xp = common.platform.endswith("_xp")
suffix = arch + ("-xp" if xp else "")
}
suffix = arch_list[common.platform]
if common.platform.endswith("_xp"): suffix += "-xp"
zip_file = "%s-%s-%s.zip" % (package_name, package_version, suffix)
inno_file = "%s-%s-%s.exe" % (package_name, package_version, suffix)
inno_help_file = "%s-Help-%s-%s.exe" % (package_name, package_version, suffix)
inno_sa_file = "%s-Standalone-%s-%s.exe" % (package_name, package_version, suffix)
inno_update_file = "update\\editors_update_%s.exe" % suffix.replace("-","_")
advinst_file = "%s-%s-%s.msi" % (package_name, package_version, suffix)
if common.clean:
utils.log_h2("desktop clean")
utils.delete_dir("build")
# utils.delete_dir("data\\vcredist")
utils.delete_dir("DesktopEditors-cache")
utils.delete_files("*.exe")
utils.delete_files("*.msi")
utils.delete_files("*.aic")
utils.delete_files("*.tmp")
utils.delete_files("*.zip")
utils.delete_files("data\\*.exe")
utils.delete_files("update\\*.exe")
utils.delete_files("update\\*.xml")
utils.delete_files("update\\*.html")
utils.log_h2("copy arifacts")
source_dir = "%s\\build_tools\\out\\%s\\%s" \
% (common.workspace_dir, common.prefix, branding.company_name)
utils.create_dir("build")
desktop_dir = "build\\" + branding.desktop_product_name_s
utils.copy_dir(source_dir + "\\" + branding.desktop_product_name_s, desktop_dir)
if not branding.onlyoffice:
viewer_dir = "build\\" + branding.viewer_product_name_s
utils.copy_dir(source_dir + "\\" + branding.viewer_product_name_s, viewer_dir)
make_prepare()
make_zip()
vcdl = True
vcdl &= download_vcredist("2013")
vcdl &= download_vcredist("2022")
if not vcdl:
utils.set_summary("desktop inno build", False)
utils.set_summary("desktop inno standalone build", False)
utils.set_summary("desktop inno update build", False)
utils.set_summary("desktop advinst build", False)
utils.set_cwd(common.workspace_dir)
return
make_inno()
make_advinst()
make_online()
if common.platform == "windows_x64":
make_update_files()
if common.platform in ["windows_x64", "windows_x86"]:
make_advinst()
utils.set_cwd(common.workspace_dir)
return
def make_prepare():
args = [
"-Version", package_version,
"-Arch", arch
]
if xp:
args += ["-Target", "xp"]
if common.sign:
args += ["-Sign"]
utils.log_h2("desktop prepare")
ret = utils.ps1("make.ps1", args, verbose=True)
utils.set_summary("desktop prepare", ret)
return
def make_zip():
zip_file = "%s-%s-%s.zip" % (package_name, package_version, suffix)
args = [
"-Version", package_version,
"-Arch", arch
]
if xp:
args += ["-Target", "xp"]
# if common.sign:
# args += ["-Sign"]
utils.log_h2("desktop zip build")
ret = utils.ps1("make_zip.ps1", args, verbose=True)
args = ["-DesktopPath", desktop_dir, "-OutFile", zip_file]
if common.sign:
args += ["-Sign", "-CertName", branding.cert_name]
if branding.onlyoffice and not common.platform.endswith("_xp"):
args += ["-ExcludeHelp"]
ret = utils.ps1(
"make_zip.ps1", args, creates=zip_file, verbose=True
)
utils.set_summary("desktop zip build", ret)
if common.deploy and ret:
utils.log_h2("desktop zip deploy")
ret = s3_upload([zip_file], "desktop/win/generic/")
ret = aws_s3_upload([zip_file], "win/generic/", "Portable")
utils.set_summary("desktop zip 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)
args = [
"-Version", package_version,
"-Arch", arch
]
if common.sign:
args += ["-Sign"]
def download_vcredist(year):
utils.log_h2("vcredist " + year + " download")
arch = arch_list[common.platform]
link = common.vcredist_links[year][arch]["url"]
md5 = common.vcredist_links[year][arch]["md5"]
vcredist_file = "data\\vcredist\\vcredist_%s_%s.exe" % (year, arch)
utils.log_h2(vcredist_file)
utils.create_dir(utils.get_dirname(vcredist_file))
ret = utils.download_file(link, vcredist_file, md5, verbose=True)
utils.set_summary("vcredist " + year + " download", ret)
return ret
def make_inno():
utils.log_h2("desktop inno build")
if xp:
ret = utils.ps1("make_inno.ps1", args + ["-Target", "xp"], verbose=True)
inno_arch_list = {
"windows_x64": "64",
"windows_x86": "32",
"windows_x64_xp": "64",
"windows_x86_xp": "32"
}
iscc_args = [
"/Qp",
"/DVERSION=" + package_version,
"/DsAppVersion=" + package_version,
"/DDEPLOY_PATH=" + desktop_dir,
"/DARCH=" + arch_list[common.platform],
"/D_ARCH=" + inno_arch_list[common.platform],
]
if branding.onlyoffice:
iscc_args.append("/D_ONLYOFFICE=1")
else:
ret = utils.ps1("make_inno.ps1", args, verbose=True)
iscc_args.append("/DsBrandingFolder=" + \
utils.get_abspath(common.workspace_dir + "\\" + common.branding + "\\desktop-apps"))
if common.platform.endswith("_xp"):
iscc_args.append("/D_WIN_XP=1")
if common.sign:
iscc_args.append("/DENABLE_SIGNING=1")
iscc_args.append("/Sbyparam=signtool.exe sign /a /v /n $q" + \
branding.cert_name + "$q /t " + common.tsa_server + " $f")
args = ["iscc"] + iscc_args + ["common.iss"]
ret = utils.cmd(*args, creates=inno_file, verbose=True)
utils.set_summary("desktop inno build", ret)
if branding.onlyoffice and not xp:
utils.log_h2("desktop inno standalone")
ret = utils.ps1("make_inno.ps1", args + ["-Target", "standalone"], verbose=True)
if branding.onlyoffice and not common.platform.endswith("_xp"):
args = ["iscc"] + iscc_args + ["help.iss"]
ret = utils.cmd(*args, creates=inno_help_file, verbose=True)
utils.set_summary("desktop inno help build", ret)
args = ["iscc"] + iscc_args + ["/DEMBED_HELP", "/DsPackageEdition=Standalone", "common.iss"]
ret = utils.cmd(*args, creates=inno_sa_file, verbose=True)
utils.set_summary("desktop inno standalone build", ret)
if update_wrapper and not xp:
utils.log_h2("desktop inno update build")
ret = utils.ps1("make_inno.ps1", args + ["-Target", "update"], verbose=True)
if not (hasattr(branding, 'desktop_updates_skip_iss_wrapper') and branding.desktop_updates_skip_iss_wrapper):
args = ["iscc"] + iscc_args + ["/DTARGET_NAME=" + inno_file, "update_common.iss"]
ret = utils.cmd(*args, creates=inno_update_file, 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/")
ret = aws_s3_upload([inno_file], "win/inno/","Installer")
utils.set_summary("desktop inno deploy", ret)
if branding.onlyoffice and not xp:
if branding.onlyoffice and not common.platform.endswith("_xp"):
utils.log_h2("desktop inno help deploy")
ret = aws_s3_upload([inno_help_file], "win/inno/","Installer")
utils.set_summary("desktop inno help deploy", ret)
utils.log_h2("desktop inno standalone deploy")
ret = s3_upload([inno_sa_file], "desktop/win/inno/")
ret = aws_s3_upload([inno_sa_file], "win/inno/","Installer")
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/")
ret = aws_s3_upload(
[inno_update_file],
"win/inno/%s/%s/" % (common.version, common.build),
"Update"
)
elif utils.is_file(inno_file):
ret = s3_upload([inno_file], "desktop/win/inno/" + inno_update_file)
ret = aws_s3_upload(
[inno_file],
"win/inno/%s/%s/%s" % (common.version, common.build, utils.get_basename(inno_update_file)),
"Update"
)
else:
ret = False
utils.set_summary("desktop inno update 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"]
def make_update_files():
utils.log_h2("desktop update files build")
changes_dir = common.workspace_dir + "\\" + utils.get_path(branding.desktop_changes_dir) + "\\" + common.version
if common.deploy and utils.glob_path(changes_dir + "\\*.html"):
utils.log_h2("desktop update files deploy")
ret = aws_s3_upload(
utils.glob_path(changes_dir + "\\*.html"),
"win/update/%s/%s/" % (common.version, common.build),
"Update"
)
utils.set_summary("desktop update files deploy", ret)
return
def make_advinst():
utils.log_h2("desktop advinst build")
ret = utils.ps1("make_advinst.ps1", args, verbose=True)
arch = arch_list[common.platform]
if not branding.onlyoffice:
branding_path = common.workspace_dir + "\\" + common.branding
utils.copy_dir_content(
branding_path + "\\desktop-apps\\win-linux\\package\\windows\\data", "data", ".bmp")
utils.copy_dir_content(
branding_path + "\\desktop-apps\\win-linux\\package\\windows\\data", "data", ".png")
utils.copy_dir_content(
branding_path + "\\desktop-apps\\win-linux\\extras\\projicons\\res",
"..\\..\\extras\\projicons\\res", ".ico")
utils.copy_file(
branding_path + "\\desktop-apps\\win-linux\\package\\windows\\dictionary.ail",
"dictionary.ail")
utils.copy_file(
branding_path + "\\desktop-apps\\common\\package\\license\\eula_" + common.branding + ".rtf",
"..\\..\\..\\common\\package\\license\\agpl-3.0.rtf")
utils.copy_file(
branding_path + "\\multimedia\\videoplayer\\icons\\" + common.branding + ".ico",
"..\\..\\extras\\projicons\\res\\media.ico")
utils.copy_file(
branding_path + "\\multimedia\\imageviewer\\icons\\ico\\" + common.branding + ".ico",
"..\\..\\extras\\projicons\\res\\gallery.ico")
aic_content = [";aic"]
if not common.sign:
aic_content += [
"ResetSig"
]
if arch == "x64":
aic_content += [
"SetPackageType x64 -buildname DefaultBuild",
"AddOsLc -buildname DefaultBuild -arch x64",
"DelOsLc -buildname DefaultBuild -arch x86",
'DelPrerequisite "Microsoft Visual C++ 2015-2022 Redistributable (x86)"',
'DelPrerequisite "Microsoft Visual C++ 2013 Redistributable (x86)"'
]
if arch == "x86":
aic_content += [
"SetPackageType x86 -buildname DefaultBuild",
"AddOsLc -arch x86 -buildname DefaultBuild",
"DelOsLc -arch x64 -buildname DefaultBuild",
"SetAppdir -path [ProgramFilesFolder][MANUFACTURER_INSTALL_FOLDER]\\[PRODUCT_INSTALL_FOLDER] -buildname DefaultBuild",
'DelPrerequisite "Microsoft Visual C++ 2015-2022 Redistributable (x64)"',
'DelPrerequisite "Microsoft Visual C++ 2013 Redistributable (x64)"'
]
if branding.onlyoffice:
for path in utils.glob_path(desktop_dir + "\\editors\\web-apps\\apps\\*\\main\\resources\\help"):
utils.delete_dir(path)
aic_content += [
"DelFolder CUSTOM_PATH"
]
else:
utils.replace_in_file('DesktopEditors.aip','(<ROW Property="UpgradeCode" Value=")(.*)("/>)', r'\1%s\3' % (branding.desktop_upgrade_code))
aic_content += [
"AddUpgradeCode {47EEF706-B0E4-4C43-944B-E5F914B92B79} \
-min_ver 7.1.1 -include_min_ver \
-max_ver 7.2.2 -include_max_ver \
-include_lang 1049 \
-property_name UPGRADE_2 -enable_migrate",
"DelLanguage 1029 -buildname DefaultBuild",
"DelLanguage 1031 -buildname DefaultBuild",
"DelLanguage 1041 -buildname DefaultBuild",
"DelLanguage 1046 -buildname DefaultBuild",
"DelLanguage 2070 -buildname DefaultBuild",
"DelLanguage 1060 -buildname DefaultBuild",
"DelLanguage 1036 -buildname DefaultBuild",
"DelLanguage 3082 -buildname DefaultBuild",
"DelLanguage 1033 -buildname DefaultBuild",
"SetCurrentFeature ExtendedFeature",
"NewSync CUSTOM_PATH " + viewer_dir,
"UpdateFile CUSTOM_PATH\\ImageViewer.exe " + viewer_dir + "\\ImageViewer.exe",
"UpdateFile CUSTOM_PATH\\VideoPlayer.exe " + viewer_dir + "\\VideoPlayer.exe",
"SetProperty ProductName=\"" + branding.desktop_product_name_full + "\"",
"SetProperty ASCC_REG_PREFIX=" + branding.ascc_reg_prefix
]
aic_content += [
"SetCurrentFeature MainFeature",
"NewSync APPDIR " + desktop_dir,
"UpdateFile APPDIR\\DesktopEditors.exe " + desktop_dir + "\\DesktopEditors.exe",
"UpdateFile APPDIR\\updatesvc.exe " + desktop_dir + "\\updatesvc.exe",
"SetVersion " + package_version,
"SetPackageName " + advinst_file + " -buildname DefaultBuild",
"Rebuild -buildslist DefaultBuild"
]
utils.write_file("DesktopEditors.aic", "\r\n".join(aic_content), "utf-8-sig")
ret = utils.cmd("AdvancedInstaller.com", "/execute", \
"DesktopEditors.aip", "DesktopEditors.aic", verbose=True)
utils.set_summary("desktop advinst build", ret)
if common.deploy and ret:
utils.log_h2("desktop advinst deploy")
ret = s3_upload([advinst_file], "desktop/win/advinst/")
ret = aws_s3_upload([advinst_file], "win/advinst/", "Installer")
utils.set_summary("desktop advinst deploy", ret)
return
def make_online():
if not common.platform in ["windows_x86_xp"]:
return
online_file = "%s-%s-%s.exe" % ("OnlineInstaller", package_version, suffix)
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
#
# macOS
#
def make_macos():
global package_name, build_dir, branding_dir, updates_dir, changes_dir, \
suffix, lane, scheme, released_updates_dir
suffix, lane, scheme, app_version
package_name = branding.desktop_package_name
build_dir = branding.desktop_build_dir
branding_dir = branding.desktop_branding_dir
@ -206,7 +367,6 @@ def make_macos():
}[common.platform]
lane = "release_" + suffix
scheme = package_name + "-" + suffix
sparkle_updates = False
utils.set_cwd(branding_dir)
@ -215,7 +375,6 @@ def make_macos():
utils.delete_dir(utils.get_env("HOME") + "/Library/Developer/Xcode/Archives")
utils.delete_dir(utils.get_env("HOME") + "/Library/Caches/Sparkle_generate_appcast")
utils.log_h2("build")
source_dir = "%s/build_tools/out/%s/%s" \
% (common.workspace_dir, common.prefix, branding.company_name)
if branding.onlyoffice:
@ -223,40 +382,32 @@ def make_macos():
+ "/desktopeditors/editors/web-apps/apps/*/main/resources/help"):
utils.delete_dir(path)
if utils.get_env("ARCHIVES_DIR"):
sparkle_updates = True
released_updates_dir = "%s/%s/_updates" % (utils.get_env("ARCHIVES_DIR"), scheme)
plistbuddy = "/usr/libexec/PlistBuddy"
plist_path = "%s/%s/ONLYOFFICE/Resources/%s-%s/Info.plist" \
% (common.workspace_dir, branding_dir, package_name, suffix)
appcast_url = branding.sparkle_base_url + "/" + suffix + "/" + branding.desktop_package_name.lower() + ".xml"
release_bundle_version_string = utils.sh_output(
'curl -Ls ' + appcast_url + ' 2> /dev/null' \
+ ' | xmllint --xpath "/rss/channel/item[1]/enclosure/@*[name()=\'sparkle:shortVersionString\']" -' \
+ ' | cut -f2 -d\\\"',
verbose=True).rstrip()
release_bundle_version = utils.sh_output(
'curl -Ls ' + appcast_url + ' 2> /dev/null' \
+ ' | xmllint --xpath "/rss/channel/item[1]/enclosure/@*[name()=\'sparkle:version\']" -' \
+ ' | cut -f2 -d\\\"',
verbose=True).rstrip()
appcast = utils.sh_output('%s -c "Print :SUFeedURL" %s' \
% (plistbuddy, plist_path), verbose=True).rstrip()
appcast = released_updates_dir + "/" + appcast[appcast.rfind("/")+1:]
app_version = common.version
bundle_version = str(int(release_bundle_version) + 1)
plist_path = "%s/%s/ONLYOFFICE/Resources/%s-%s/Info.plist" \
% (common.workspace_dir, branding.desktop_branding_dir, branding.desktop_package_name, suffix)
utils.sh('/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString %s" %s' \
% (common.version, plist_path), verbose=True)
utils.sh('/usr/libexec/PlistBuddy -c "Set :CFBundleVersion %s" %s' \
% (bundle_version, plist_path), verbose=True)
release_version_string = utils.sh_output(
'xmllint --xpath "/rss/channel/item[1]/*[name()=\'sparkle:shortVersionString\']/text()" ' + appcast,
verbose=True).rstrip()
release_version = utils.sh_output(
'xmllint --xpath "/rss/channel/item[1]/*[name()=\'sparkle:version\']/text()" ' + appcast,
verbose=True).rstrip()
bundle_version = str(int(release_version) + 1)
help_url = "https://download.onlyoffice.com/install/desktop/editors/help/v" + common.version + "/apps"
utils.sh('%s -c "Set :CFBundleShortVersionString %s" %s' \
% (plistbuddy, common.version, plist_path), verbose=True)
utils.sh('%s -c "Set :CFBundleVersion %s" %s' \
% (plistbuddy, bundle_version, plist_path), verbose=True)
utils.sh('%s -c "Set :ASCBundleBuildNumber %s" %s' \
% (plistbuddy, common.build, plist_path), verbose=True)
utils.sh('%s -c "Add :ASCWebappsHelpUrl string %s" %s' \
% (plistbuddy, help_url, plist_path), verbose=True)
utils.log("RELEASE=" + release_version_string + "(" + release_version + ")" \
+ "\nCURRENT=" + common.version + "(" + bundle_version + ")")
utils.log("RELEASE=" + release_bundle_version_string + "(" + release_bundle_version + ")" \
+ "\nCURRENT=" + common.version + "(" + bundle_version + ")")
dmg = make_dmg()
if dmg and sparkle_updates:
if dmg:
make_sparkle_updates()
utils.set_cwd(common.workspace_dir)
@ -274,36 +425,35 @@ def make_dmg():
if common.deploy and dmg:
utils.log_h2("desktop dmg deploy")
ret = s3_upload(
utils.glob_path("build/*.dmg"),
"desktop/mac/%s/%s/%s/" % (suffix, common.version, common.build))
ret = aws_s3_upload(
utils.glob_path("build/*.dmg"),
"mac/%s/%s/%s/" % (common.version, common.build, suffix),
"Disk Image"
)
utils.set_summary("desktop dmg deploy", ret)
utils.log_h2("desktop zip deploy")
ret = s3_upload(
["build/%s-%s.zip" % (scheme, common.version)],
"desktop/mac/%s/%s/%s/" % (suffix, common.version, common.build))
ret = aws_s3_upload(
["build/%s-%s.zip" % (scheme, app_version)],
"mac/%s/%s/%s/" % (common.version, common.build, suffix),
"Archive"
)
utils.set_summary("desktop zip deploy", ret)
return dmg
def make_sparkle_updates():
utils.log_h2("desktop sparkle files build")
zip_filename = scheme + '-' + common.version
zip_filename = scheme + '-' + app_version
macos_zip = "build/" + zip_filename + ".zip"
updates_storage_dir = "%s/%s/_updates" % (utils.get_env('ARCHIVES_DIR'), scheme)
utils.create_dir(updates_dir)
utils.copy_file(macos_zip, updates_dir)
utils.sh(
"ls -1t " + released_updates_dir + "/*.zip" \
+ " | head -n 3" \
+ " | while read f; do cp -fv \"$f\" " + updates_dir + "/; done",
verbose=True)
utils.copy_dir_content(updates_storage_dir, updates_dir, ".zip")
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")
for file in utils.glob_path(changes_dir + "/" + app_version + "/*.html"):
filename = utils.get_basename(file).replace("changes", zip_filename)
utils.copy_file(file, updates_dir + "/" + filename)
sparkle_base_url = "%s/%s/updates/" % (branding.sparkle_base_url, suffix)
ret = utils.sh(
@ -316,14 +466,48 @@ def make_sparkle_updates():
)
utils.set_summary("desktop sparkle files build", ret)
# utils.log_h3("edit sparkle appcast links")
# appcast_url = branding.sparkle_base_url + "/" + suffix
# appcast = "%s/%s.xml" % (updates_dir, package_name.lower())
# for lang, base in update_changes_list.items():
# if base == "ReleaseNotes":
# utils.replace_in_file(appcast,
# r'(<sparkle:releaseNotesLink>.+/).+(\.html</sparkle:releaseNotesLink>)',
# "\\1" + base + "\\2")
# else:
# utils.replace_in_file(appcast,
# r'(<sparkle:releaseNotesLink xml:lang="' + lang + r'">).+(\.html</sparkle:releaseNotesLink>)',
# "\\1" + base + "\\2")
utils.log("")
utils.log_h3("generate checksums")
utils.sh(
"md5 *.zip *.delta > md5sums.txt",
chdir="build/update", verbose=True
)
utils.sh(
"shasum -a 256 *.zip *.delta > sha256sums.txt",
chdir="build/update", verbose=True
)
if common.deploy:
utils.log_h2("desktop sparkle files deploy")
ret = s3_upload(
utils.glob_path("build/update/*.delta") \
+ utils.glob_path("build/update/*.xml") \
+ utils.glob_path("build/update/*.html"),
"desktop/mac/%s/%s/%s/" % (suffix, common.version, common.build))
ret = aws_s3_upload(
utils.glob_path("build/update/*.delta") \
+ utils.glob_path("build/update/*.xml") \
+ utils.glob_path("build/update/*.html"),
"mac/%s/%s/%s/" % (common.version, common.build, suffix),
"Sparkle"
)
utils.set_summary("desktop sparkle files deploy", ret)
utils.log_h2("desktop checksums deploy")
ret = aws_s3_upload(
utils.glob_path("build/update/*.txt"),
"mac/%s/%s/%s/" % (common.version, common.build, suffix),
"Checksums"
)
utils.set_summary("desktop checksums deploy", ret)
return
#
@ -334,7 +518,7 @@ 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]
make_args = branding.desktop_make_targets
if common.platform == "linux_aarch64":
make_args += ["-e", "UNAME_M=aarch64"]
if not branding.onlyoffice:
@ -342,11 +526,102 @@ def make_linux():
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
utils.set_summary("desktop build", ret)
rpm_arch = "x86_64"
if common.platform == "linux_aarch64": rpm_arch = "aarch64"
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)
utils.log_h2("desktop deploy")
if ret:
utils.log_h2("desktop tar deploy")
if "tar" in branding.desktop_make_targets:
ret = aws_s3_upload(
utils.glob_path("tar/*.tar*"),
"linux/generic/", "Portable"
)
utils.set_summary("desktop tar deploy", ret)
if "deb" in branding.desktop_make_targets:
utils.log_h2("desktop deb deploy")
ret = aws_s3_upload(
utils.glob_path("deb/*.deb"),
"linux/debian/", "Debian"
)
utils.set_summary("desktop deb deploy", ret)
if "deb-astra" in branding.desktop_make_targets:
utils.log_h2("desktop deb-astra deploy")
ret = aws_s3_upload(
utils.glob_path("deb-astra/*.deb"),
"linux/astra/", "Astra Linux Special Edition"
)
utils.set_summary("desktop deb-astra deploy", ret)
if "rpm" in branding.desktop_make_targets:
utils.log_h2("desktop rpm deploy")
ret = aws_s3_upload(
utils.glob_path("rpm/builddir/RPMS/" + rpm_arch + "/*.rpm") \
+ utils.glob_path("rpm/builddir/RPMS/noarch/*.rpm"),
"linux/rhel/", "CentOS"
)
utils.set_summary("desktop rpm deploy", ret)
if "suse-rpm" in branding.desktop_make_targets:
utils.log_h2("desktop suse-rpm deploy")
ret = aws_s3_upload(
utils.glob_path("suse-rpm/builddir/RPMS/" + rpm_arch + "/*.rpm") \
+ utils.glob_path("suse-rpm/builddir/RPMS/noarch/*.rpm"),
"linux/suse/", "SUSE Linux"
)
utils.set_summary("desktop suse-rpm deploy", ret)
if "apt-rpm" in branding.desktop_make_targets:
utils.log_h2("desktop apt-rpm deploy")
ret = aws_s3_upload(
utils.glob_path("apt-rpm/builddir/RPMS/" + rpm_arch + "/*.rpm") \
+ utils.glob_path("apt-rpm/builddir/RPMS/noarch/*.rpm"),
"linux/altlinux/", "ALT Linux"
)
utils.set_summary("desktop apt-rpm deploy", ret)
if "urpmi" in branding.desktop_make_targets:
utils.log_h2("desktop urpmi deploy")
ret = aws_s3_upload(
utils.glob_path("urpmi/builddir/RPMS/" + rpm_arch + "/*.rpm") \
+ utils.glob_path("urpmi/builddir/RPMS/noarch/*.rpm"),
"linux/rosa/", "ROSA"
)
utils.set_summary("desktop urpmi deploy", ret)
else:
if "tar" in branding.desktop_make_targets:
utils.set_summary("desktop tar deploy", False)
if "deb" in branding.desktop_make_targets:
utils.set_summary("desktop deb deploy", False)
if "deb-astra" in branding.desktop_make_targets:
utils.set_summary("desktop deb-astra deploy", False)
if "rpm" in branding.desktop_make_targets:
utils.set_summary("desktop rpm deploy", False)
if "suse-rpm" in branding.desktop_make_targets:
utils.set_summary("desktop suse-rpm deploy", False)
if "apt-rpm" in branding.desktop_make_targets:
utils.set_summary("desktop apt-rpm deploy", False)
if "urpmi" in branding.desktop_make_targets:
utils.set_summary("desktop urpmi deploy", False)
utils.set_cwd(common.workspace_dir)
make_appimage()
return
def make_appimage():
if not onlyoffice:
return
if not utils.is_file("desktop-apps/win-linux/package/linux/deb/onlyoffice-desktopeditors_%s-%s_amd64.deb" % (common.version, common.build))
return
utils.set_cwd("appimage-desktopeditors")
rc = utils.sh("make clean", verbose=True)
common.summary["desktop appimage clean"] = rc
# args = []
# if common.platform == "linux_aarch64":
# args += ["-e", "UNAME_M=aarch64"]
rc = utils.sh("make testing", verbose=True)
common.summary["desktop appimage build"] = rc
utils.set_cwd(common.workspace_dir)
return

View File

@ -15,23 +15,31 @@ def make():
def make_mobile():
utils.set_cwd("build_tools/out")
zip_file = "build-" + common.version + "-" + common.build + ".zip"
if common.clean:
utils.log_h2("mobile clean")
utils.sh("rm -rfv *.zip", verbose=True)
zip_file = "build-" + common.version + "-" + common.build + ".zip"
s3_key = "mobile/android/" + zip_file
utils.log_h2("mobile build")
ret = utils.sh("zip -r " + zip_file + " ./android ./ios", verbose=True)
ret = utils.sh("zip -r " + zip_file + " ./android* ./js", verbose=True)
utils.set_summary("mobile build", ret)
if common.deploy:
utils.log_h2("mobile deploy")
if not utils.is_file(zip_file):
utils.log_err("file not exist: " + zip_file)
ret = False
elif ret:
ret = utils.sh(
"aws s3 cp --acl public-read --no-progress " \
+ "--metadata md5=" + utils.get_md5(zip_file) + " " \
+ zip_file + " s3://" + branding.s3_bucket + "/" + s3_key,
verbose=True
)
if ret:
utils.log_h2("mobile deploy")
key = "mobile/android/" + zip_file
ret = utils.s3_upload(zip_file, "s3://" + branding.s3_bucket + "/" + key)
if ret:
utils.log("URL: " + branding.s3_base_url + "/" + key)
utils.add_deploy_data("mobile", "Android", zip_file, s3_key)
utils.set_summary("mobile deploy", ret)
utils.set_cwd(common.workspace_dir)

View File

@ -14,15 +14,33 @@ def make(edition):
utils.log("Unsupported host OS")
return
def s3_upload(files, dst):
if not files: return False
def aws_s3_upload(files, key, edition, ptype=None):
if not files:
return False
ret = True
for f in files:
key = dst + utils.get_basename(f) if dst.endswith("/") else dst
upload = utils.s3_upload(f, "s3://" + branding.s3_bucket + "/" + key)
if upload:
utils.log("URL: " + branding.s3_base_url + "/" + key)
key = "server/" + key
for file in files:
if not utils.is_file(file):
utils.log_err("file not exist: " + file)
ret &= False
continue
args = ["aws"]
if hasattr(branding, "s3_endpoint_url"):
args += ["--endpoint-url=" + branding.s3_endpoint_url]
args += [
"s3", "cp", "--no-progress", "--acl", "public-read",
"--metadata", "md5=" + utils.get_md5(file),
file, "s3://" + branding.s3_bucket + "/" + key
]
if common.os_family == "windows":
upload = utils.cmd(*args, verbose=True)
else:
upload = utils.sh(" ".join(args), verbose=True)
ret &= upload
if upload and ptype is not None:
full_key = key
if full_key.endswith("/"): full_key += utils.get_basename(file)
utils.add_deploy_data("server_" + edition, ptype, file, full_key)
return ret
def make_windows(edition):
@ -36,18 +54,18 @@ def make_windows(edition):
utils.log_h2("server " + edition + " build")
ret = utils.cmd("make", "clean", verbose=True)
if edition == "prerequisites":
make_args = ["exe-pr"]
else:
make_args = ["exe", "-e", "PRODUCT_NAME=" + product_name]
args = ["-e", "PRODUCT_NAME=" + product_name]
if not branding.onlyoffice:
make_args += ["-e", "BRANDING_DIR=../" + common.branding + "/document-server-package"]
ret &= utils.cmd("make", *make_args, verbose=True)
args += ["-e", "BRANDING_DIR=../" + common.branding + "/document-server-package"]
ret &= utils.cmd("make", "packages", *args, verbose=True)
utils.set_summary("server " + edition + " build", ret)
if common.deploy and ret:
utils.log_h2("server " + edition + " inno deploy")
ret = s3_upload(utils.glob_path("exe/*.exe"), "server/win/inno/")
ret = aws_s3_upload(
utils.glob_path("exe/*.exe"),
"win/inno/", edition, "Installer"
)
utils.set_summary("server " + edition + " inno deploy", ret)
utils.set_cwd(common.workspace_dir)
@ -63,8 +81,7 @@ def make_linux(edition):
utils.set_cwd("document-server-package")
utils.log_h2("server " + edition + " build")
make_args = [t["make"] for t in branding.server_make_targets]
make_args += ["-e", "PRODUCT_NAME=" + product_name]
make_args = branding.server_make_targets + ["-e", "PRODUCT_NAME=" + product_name]
if common.platform == "linux_aarch64":
make_args += ["-e", "UNAME_M=aarch64"]
if not branding.onlyoffice:
@ -72,11 +89,49 @@ def make_linux(edition):
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
utils.set_summary("server " + edition + " build", ret)
rpm_arch = "x86_64"
if common.platform == "linux_aarch64": rpm_arch = "aarch64"
if common.deploy:
for t in branding.server_make_targets:
utils.log_h2("server " + edition + " " + t["make"] + " deploy")
ret = s3_upload(utils.glob_path(t["src"]), t["dst"])
utils.set_summary("server " + edition + " " + t["make"] + " deploy", ret)
utils.log_h2("server " + edition + " deploy")
if ret:
if "deb" in branding.server_make_targets:
utils.log_h2("server " + edition + " deb deploy")
ret = aws_s3_upload(
utils.glob_path("deb/*.deb"),
"linux/debian/", edition, "Debian"
)
utils.set_summary("server " + edition + " deb deploy", ret)
if "rpm" in branding.server_make_targets:
utils.log_h2("server " + edition + " rpm deploy")
ret = aws_s3_upload(
utils.glob_path("rpm/builddir/RPMS/" + rpm_arch + "/*.rpm"),
"linux/rhel/", edition, "CentOS"
)
utils.set_summary("server " + edition + " rpm deploy", ret)
if "apt-rpm" in branding.server_make_targets:
utils.log_h2("server " + edition + " apt-rpm deploy")
ret = aws_s3_upload(
utils.glob_path("apt-rpm/builddir/RPMS/" + rpm_arch + "/*.rpm"),
"linux/altlinux/", edition, "ALT Linux"
)
utils.set_summary("server " + edition + " apt-rpm deploy", ret)
if "tar" in branding.server_make_targets:
utils.log_h2("server " + edition + " snap deploy")
ret = aws_s3_upload(
utils.glob_path("*.tar.gz"),
"linux/generic/", edition, "Snap"
)
utils.set_summary("server " + edition + " snap deploy", ret)
else:
if "deb" in branding.server_make_targets:
utils.set_summary("server " + edition + " deb deploy", False)
if "rpm" in branding.server_make_targets:
utils.set_summary("server " + edition + " rpm deploy", False)
if "apt-rpm" in branding.server_make_targets:
utils.set_summary("server " + edition + " apt-rpm deploy", False)
if "tar" in branding.server_make_targets:
utils.set_summary("server " + edition + " snap deploy", False)
utils.set_cwd(common.workspace_dir)
return

View File

@ -4,6 +4,7 @@
import codecs
import glob
import hashlib
import json
import os
import platform
import re
@ -72,9 +73,6 @@ def get_path(path):
return path.replace("/", "\\")
return path
def get_relpath(path, rel_path):
return os.path.relpath(get_path(path), get_path(rel_path))
def get_abspath(path):
return os.path.abspath(get_path(path))
@ -109,25 +107,11 @@ def glob_file(path):
return glob.glob(path)[0]
return
def get_hash_sha256(path):
def get_md5(path):
if os.path.exists(path):
h = hashlib.sha256()
h.update(open(path, "rb").read())
return h.hexdigest()
return
def get_hash_sha1(path):
if os.path.exists(path):
h = hashlib.sha1()
h.update(open(path, "rb").read())
return h.hexdigest()
return
def get_hash_md5(path):
if os.path.exists(path):
h = hashlib.md5()
h.update(open(path, "rb").read())
return h.hexdigest()
md5_hash = hashlib.md5()
md5_hash.update(open(path, "rb").read())
return md5_hash.hexdigest()
return
def create_dir(path, verbose=True):
@ -174,7 +158,7 @@ def copy_file(src, dst, verbose=True):
log(" src: " + src)
log(" dst: " + dst)
if is_file(dst):
delete_file(dst, False)
delete_file(dst)
if not is_file(src):
log_err("file not exist: " + src)
return
@ -201,12 +185,18 @@ def copy_files(src, dst, override=True, verbose=True):
copy_files(file + "/*", dst + "/" + file_name, override)
return
def copy_dir(src, dst, verbose=True):
def copy_dir(src, dst, override=True, verbose=True):
if verbose:
log("- copy_dir:")
log(" src: " + src)
log(" dst: " + dst)
shutil.copytree(src, dst)
log(" override: " + str(override))
if is_dir(dst):
delete_dir(dst)
try:
shutil.copytree(get_path(src), get_path(dst))
except OSError as e:
log_err('directory not copied. Error: %s' % e)
return
def copy_dir_content(src, dst, filter_include = "", filter_exclude = "", verbose=True):
@ -216,18 +206,20 @@ def copy_dir_content(src, dst, filter_include = "", filter_exclude = "", verbose
log(" dst: " + dst)
log(" include: " + filter_include)
log(" exclude: " + filter_exclude)
for item in os.listdir(src):
s = os.path.join(src, item)
d = os.path.join(dst, item)
if ("" != filter_include) and (-1 == item.find(filter_include)):
src_folder = src
if ("/" != src[-1:]):
src_folder += "/"
src_folder += "*"
for file in glob.glob(src_folder):
basename = os.path.basename(file)
if ("" != filter_include) and (-1 == basename.find(filter_include)):
continue
if ("" != filter_exclude) and (-1 != item.find(filter_exclude)):
if ("" != filter_exclude) and (-1 != basename.find(filter_exclude)):
continue
if os.path.isdir(s):
shutil.copytree(s, d)
else:
shutil.copy2(s, d)
log(item)
if is_file(file):
copy_file(file, dst, verbose=False)
elif is_dir(file):
copy_dir(file, dst + "/" + basename, verbose=False)
return
def delete_file(path, verbose=True):
@ -266,6 +258,20 @@ def set_summary(target, status):
common.summary.append({target: status})
return
def add_deploy_data(product, ptype, src, dst):
common.deploy_data.append({
"platform": common.platformTitles[common.platform],
"product": product,
"type": ptype,
# "local": get_path(src),
"size": get_file_size(get_path(src)),
"key": dst
})
file = open(get_path(common.workspace_dir + "/deploy.json"), 'w')
file.write(json.dumps(common.deploy_data, sort_keys=True, indent=4))
file.close()
return
def cmd(*args, **kwargs):
if kwargs.get("verbose"):
log("- cmd:")
@ -279,12 +285,12 @@ def cmd(*args, **kwargs):
return False
if kwargs.get("chdir") and is_dir(kwargs["chdir"]):
oldcwd = get_cwd()
set_cwd(kwargs["chdir"], verbose=False)
set_cwd(kwargs["chdir"])
ret = subprocess.call(
[i for i in args], stderr=subprocess.STDOUT, shell=True
) == 0
if kwargs.get("chdir") and oldcwd:
set_cwd(oldcwd, verbose=False)
set_cwd(oldcwd)
return ret
def cmd_output(*args, **kwargs):
@ -317,11 +323,33 @@ def ps1(file, args=[], **kwargs):
if kwargs.get("creates") and is_exist(kwargs["creates"]):
return True
ret = subprocess.call(
["powershell", "-ExecutionPolicy", "ByPass", "-File", file] + args,
stderr=subprocess.STDOUT, shell=True
["powershell", "-File", file] + args, stderr=subprocess.STDOUT, shell=True
) == 0
return ret
def download_file(url, path, md5, verbose=False):
if verbose:
log("- download_file:")
log(" url: " + path)
log(" path: " + url)
log(" md5: " + md5)
if is_file(path):
if get_md5(path) == md5:
log_err("file already exist (match checksum)")
return True
else:
log_err("wrong checksum (%s), delete" % md5)
os.remove(path)
ret = powershell(
"(New-Object System.Net.WebClient).DownloadFile('%s','%s')" % (url, path),
verbose=True
)
md5_new = get_md5(path)
if md5 != md5_new:
log_err("checksum didn't match (%s != %s)" % (md5, md5_new))
return False
return ret
def sh(command, **kwargs):
if kwargs.get("verbose"):
log("- sh:")
@ -335,61 +363,18 @@ def sh(command, **kwargs):
return False
if kwargs.get("chdir") and is_dir(kwargs["chdir"]):
oldcwd = get_cwd()
set_cwd(kwargs["chdir"], verbose=False)
set_cwd(kwargs["chdir"])
ret = subprocess.call(
command, stderr=subprocess.STDOUT, shell=True
) == 0
if kwargs.get("chdir") and oldcwd:
set_cwd(oldcwd, verbose=False)
set_cwd(oldcwd)
return ret
def sh_output(command, **kwargs):
if kwargs.get("verbose"):
log("- sh_output:")
log(" command: " + command)
if kwargs.get("chdir"):
log(" chdir: " + kwargs["chdir"])
if kwargs.get("chdir") and is_dir(kwargs["chdir"]):
oldcwd = get_cwd()
set_cwd(kwargs["chdir"], verbose=False)
ret = subprocess.check_output(
return subprocess.check_output(
command, stderr=subprocess.STDOUT, shell=True
).decode("utf-8")
log(ret)
if kwargs.get("chdir") and oldcwd:
set_cwd(oldcwd, verbose=False)
return ret
def s3_upload(src, dst, **kwargs):
if not is_file(src):
log_err("file not exist: " + src)
return False
metadata = "sha256=" + get_hash_sha256(src) \
+ ",sha1=" + get_hash_sha1(src) \
+ ",md5=" + get_hash_md5(src)
args = ["aws"]
if kwargs.get("endpoint_url"):
args += ["--endpoint-url", kwargs["endpoint_url"]]
args += ["s3", "cp", "--no-progress"]
if kwargs.get("acl"):
args += ["--acl", kwargs["acl"]]
args += ["--metadata", metadata, src, dst]
if is_windows():
ret = cmd(*args, verbose=True)
else:
ret = sh(" ".join(args), verbose=True)
return ret
def s3_copy(src, dst, **kwargs):
args = ["aws"]
if kwargs.get("endpoint_url"):
args += ["--endpoint-url", kwargs["endpoint_url"]]
args += ["s3", "cp", "--no-progress"]
if kwargs.get("acl"):
args += ["--acl", kwargs["acl"]]
args += [src, dst]
if is_windows():
ret = cmd(*args, verbose=True)
else:
ret = sh(" ".join(args), verbose=True)
return ret

View File

@ -1,153 +0,0 @@
#!/usr/bin/env python
import os
import sys
__dir__name__ = os.path.dirname(__file__)
sys.path.append(__dir__name__ + '/core_common/modules/android')
import base
import config
import android_ndk
import multiprocessing
def get_make_file_suffix(platform):
suffix = platform
if config.check_option("config", "debug"):
suffix += "_debug_"
suffix += config.option("branding")
return suffix
def get_j_num():
if ("0" != config.option("multiprocess")):
return ["-j" + str(multiprocessing.cpu_count())]
return []
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"):
return False
return True
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")
return
old_env = dict(os.environ)
# qt
qt_dir = base.qt_setup(platform)
base.set_env("OS_DEPLOY", platform)
# pro & makefile
file_pro = os.path.abspath(project)
pro_dir = os.path.dirname(file_pro)
if (pro_dir.endswith("/.")):
pro_dir = pro_dir[:-2]
if (pro_dir.endswith("/")):
pro_dir = pro_dir[:-1]
makefile_name = "Makefile." + get_make_file_suffix(platform)
makefile = pro_dir + "/" + makefile_name
stash_file = pro_dir + "/.qmake.stash"
old_cur = os.getcwd()
os.chdir(pro_dir)
if (base.is_file(stash_file)):
base.delete_file(stash_file)
if (base.is_file(makefile)):
base.delete_file(makefile)
base.set_env("DEST_MAKEFILE_NAME", "./" + makefile_name)
# setup android env
if (-1 != platform.find("android")):
base.set_env("ANDROID_NDK_HOST", android_ndk.host["arch"])
base.set_env("ANDROID_NDK_PLATFORM", "android-" + android_ndk.get_sdk_api())
base.set_env("PATH", qt_dir + "/bin:" + android_ndk.toolchain_dir() + "/bin:" + base.get_env("PATH"))
# setup ios env
if (-1 != platform.find("ios")):
base.hack_xcode_ios()
if base.is_file(makefile):
base.delete_file(makefile)
config_param = base.qt_config(platform)
if ("" != qmake_config_addon):
config_param += (" " + qmake_config_addon)
# qmake ADDON
qmake_addon = []
if ("" != config.option("qmake_addon")):
qmake_addon = config.option("qmake_addon").split()
clean_params = ["clean", "-f", makefile]
distclean_params = ["distclean", "-f", makefile]
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():
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++")
base.cmd(qmake_app, build_params)
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(), is_no_errors)
else:
config_params_array = base.qt_config_as_param(config_param)
config_params_string = ""
for item in config_params_array:
config_params_string += (" \"" + item + "\"")
qmake_addon_string = " ".join(qmake_addon)
if ("" != qmake_addon_string):
qmake_addon_string = " " + qmake_addon_string
qmake_bat = []
qmake_bat.append("call \"" + config.option("vs-path") + "/vcvarsall.bat\" " + ("x86" if base.platform_is_32(platform) else "x64"))
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)
if ("1" == config.option("clean")):
qmake_bat.append("call nmake " + " ".join(clean_params))
qmake_bat.append("call nmake " + " ".join(distclean_params))
qmake_bat.append("call \"" + qmake_app + "\" -nocache " + file_pro + config_params_string + qmake_addon_string)
if ("0" != config.option("multiprocess")):
qmake_bat.append("set CL=/MP")
qmake_bat.append("call nmake -f " + makefile)
base.run_as_bat(qmake_bat, is_no_errors)
if (base.is_file(stash_file)):
base.delete_file(stash_file)
os.chdir(old_cur)
os.environ.clear()
os.environ.update(old_env)
return
def make_all_platforms(project, qmake_config_addon=""):
platforms = config.option("platform").split()
for platform in platforms:
if not platform in config.platforms:
continue
print("------------------------------------------")
print("BUILD_PLATFORM: " + platform)
print("------------------------------------------")
make(platform, project, qmake_config_addon)
return

View File

@ -2,8 +2,6 @@
import os
import shutil
import re
import argparse
def readFile(path):
with open(path, "r", errors='replace') as file:
filedata = file.read()
@ -13,7 +11,7 @@ def writeFile(path, content):
if (os.path.isfile(path)):
os.remove(path)
with open(path, "w", encoding='utf-8') as file:
with open(path, "w") as file:
file.write(content)
return
@ -114,8 +112,6 @@ class EditorApi(object):
line = line.replace("}", "")
lineWithoutSpaces = line.replace(" ", "")
if not is_found_function and 0 == line.find("function "):
if -1 == decoration.find("@constructor"):
return
codeCorrect += (line + addon_for_func + "\n")
is_found_function = True
if not is_found_function and -1 != line.find(".prototype."):
@ -160,12 +156,6 @@ 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")
@ -187,7 +177,7 @@ class EditorApi(object):
def generate(self):
for file in self.files:
file_content = readFile(f'{sdkjs_dir}/{file}')
file_content = readFile(file)
arrRecords = file_content.split("/**")
arrRecords = arrRecords[1:-1]
for record in arrRecords:
@ -195,8 +185,8 @@ class EditorApi(object):
self.numfile += 1
correctContent = ''.join(self.records)
correctContent += "\n"
os.mkdir(args.destination + self.folder)
writeFile(args.destination + self.folder + "/api.js", correctContent)
os.mkdir('deploy/api_builder/' + self.folder)
writeFile("deploy/api_builder/" + self.folder + "/api.js", correctContent)
return
def convert_to_interface(arrFiles, sEditorType):
@ -205,27 +195,12 @@ def convert_to_interface(arrFiles, sEditorType):
editor.generate()
return
sdkjs_dir = "../../../sdkjs"
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="../../../web-apps/vendor/monaco/libs/" # Default value
)
args = parser.parse_args()
old_cur = os.getcwd()
if True == os.path.isdir(args.destination):
shutil.rmtree(args.destination, ignore_errors=True)
os.mkdir(args.destination)
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)
old_cur = os.getcwd()
os.chdir("../../../sdkjs")
if True == os.path.isdir('deploy/api_builder'):
shutil.rmtree('deploy/api_builder', ignore_errors=True)
os.mkdir('deploy/api_builder')
convert_to_interface(["word/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)

View File

@ -1,138 +0,0 @@
# Documentation Generation Guide
This guide explains how to generate documentation for Onlyoffice Builder
and Plugins (Methods/Events) API using the following Python scripts:
- `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`
## Requirements
```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
### `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
`../../../../office-js-api-declarations/office-js-api`.
### `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
`../../../../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.
- The output directories will be created if they do not exist.

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../sdkjs/cell/plugin-events.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../sdkjs/common/base-plugin-events.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../sdkjs/slide/plugin-events.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../sdkjs/word/plugin-events.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,85 +0,0 @@
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);
}
};

View File

@ -1,110 +0,0 @@
import os
import subprocess
import json
import argparse
import re
# Configuration files
configs = [
"./config/plugins/events/common.json",
"./config/plugins/events/word.json",
"./config/plugins/events/cell.json",
"./config/plugins/events/slide.json"
]
root = '../../../..'
def generate(output_dir, md=False):
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 builder 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/events"
)
args = parser.parse_args()
generate(args.destination)

View File

@ -1,356 +0,0 @@
#!/usr/bin/env python3
import os
import json
import re
import shutil
import argparse
import generate_docs_plugins_events_json
# Папки для каждого editor_name
editors = {
"word": "text-document-api",
"cell": "spreadsheet-api",
"slide": "presentation-api"
}
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=''):
"""
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.'
# Line breaks
string = string.replace('\r', '\\\n')
# Replace <b> tags with Markdown bold formatting
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/manifest/',
'/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('/plugins/methods/'):
url = f'../../{ref.split('/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/{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", "true", "false"}
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"[{base}]({root}Enumeration/{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('<', '&lt;').replace('>', '&gt;')
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', '')))
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"# {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/{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_properties_markdown(properties, enumerations, 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))
prop_types = prop['type']['names'] if prop.get('type') else []
param_types_md = generate_data_types_markdown(prop_types, enumerations, root)
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
# Escape outside code blocks
return escape_text_outside_code_blocks(content)
def process_events(data, events_root):
enumerations = []
events = []
for doclet in data:
kind = doclet.get('kind')
if kind == 'typedef':
enumerations.append(doclet)
elif kind == 'event':
events.append(doclet)
os.makedirs(events_root, exist_ok=True)
used_enumerations.clear()
# пишем события
for ev in events:
path = os.path.join(events_root, 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_root))
# пишем перечисления, используемые событиями
enum_dir = os.path.join(events_root, 'Enumeration')
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"{e['name']}.md")
write_markdown_file(path, generate_enumeration_markdown(e, enumerations))
if not e.get('examples'):
missing_examples.append(os.path.relpath(path, events_root))
def generate_events(output_dir):
if output_dir.endswith('/'):
output_dir = output_dir[:-1]
tmp = os.path.join(output_dir, 'tmp_json')
shutil.rmtree(output_dir, ignore_errors=True)
generate_docs_plugins_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="../../../../api.onlyoffice.com/site/docs/plugin-and-macros/interacting-with-editors/events/",
help="Output directory"
)
args = parser.parse_args()
generate_events(args.destination)

View File

@ -1,39 +0,0 @@
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

View File

@ -1,16 +0,0 @@
{
"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
}
}
}

View File

@ -1,221 +0,0 @@
exports.handlers = {
processingComplete: function(e) {
// array for filtered doclets
let filteredDoclets = [];
const cleanName = name => name ? name.replace('<anonymous>~', '').replaceAll('"', '') : name;
const classesDocletsMap = {}; // doclets for classes write at the end
let passedClasses = []; // passed classes for current editor
// Remove dublicates doclets
const latestDoclets = {};
e.doclets.forEach(doclet => {
const isMethod = doclet.kind === 'function' || doclet.kind === 'method';
const hasTypeofEditorsTag = isMethod && doclet.tags && doclet.tags.some(tag => tag.title === 'typeofeditors' && tag.value.includes(process.env.EDITOR));
const shouldAddMethod =
doclet.kind !== 'member' &&
(!doclet.longname || doclet.longname.search('private') === -1) &&
doclet.scope !== 'inner' && hasTypeofEditorsTag;
if (shouldAddMethod || doclet.kind == 'typedef' || doclet.kind == 'class') {
latestDoclets[doclet.longname] = doclet;
}
});
e.doclets.splice(0, e.doclets.length, ...Object.values(latestDoclets));
// check available classess for current editor
for (let i = 0; i < e.doclets.length; i++) {
const doclet = e.doclets[i];
const isMethod = doclet.kind === 'function' || doclet.kind === 'method';
const hasTypeofEditorsTag = isMethod && doclet.tags && doclet.tags.some(tag => tag.title === 'typeofeditors' && tag.value.includes(process.env.EDITOR));
const shouldAdd =
doclet.kind !== 'member' &&
(!doclet.longname || doclet.longname.search('private') === -1) &&
doclet.scope !== 'inner' &&
(!isMethod || hasTypeofEditorsTag);
if (shouldAdd) {
if (doclet.memberof && false == passedClasses.includes(cleanName(doclet.memberof))) {
passedClasses.push(cleanName(doclet.memberof));
}
}
else if (doclet.kind == 'class') {
classesDocletsMap[cleanName(doclet.name)] = doclet;
}
}
// remove unavailave classes in current editor
passedClasses = passedClasses.filter(className => {
const doclet = classesDocletsMap[className];
if (!doclet) {
return true;
}
const hasTypeofEditorsTag = !!(doclet.tags && doclet.tags.some(tag => tag.title === 'typeofeditors'));
// class is passes if there is no editor tag or the current editor is among the tags
const isPassed = false == hasTypeofEditorsTag || doclet.tags.some(tag => tag.title === 'typeofeditors' && tag.value && tag.value.includes(process.env.EDITOR));
return isPassed;
});
for (let i = 0; i < e.doclets.length; i++) {
const doclet = e.doclets[i];
const isMethod = doclet.kind === 'function' || doclet.kind === 'method';
const hasTypeofEditorsTag = isMethod && doclet.tags && doclet.tags.some(tag => tag.title === 'typeofeditors' && tag.value.includes(process.env.EDITOR));
const shouldAddMethod =
doclet.kind !== 'member' &&
(!doclet.longname || doclet.longname.search('private') === -1) &&
doclet.scope !== 'inner' && hasTypeofEditorsTag;
if (shouldAddMethod) {
// if the class is not in our map, then we deleted it ourselves -> not available in the editor
if (false == passedClasses.includes(cleanName(doclet.memberof))) {
continue;
}
// We leave only the necessary fields
doclet.memberof = cleanName(doclet.memberof);
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,
memberof: cleanName(doclet.memberof),
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,
name: doclet.name,
longname: cleanName(doclet.longname),
kind: doclet.kind,
scope: doclet.scope,
type: doclet.type ? {
names: doclet.type.names,
parsedType: doclet.type.parsedType
} : doclet.type,
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,
meta: doclet.meta ? {
lineno: doclet.meta.lineno,
columnno: doclet.meta.columnno
} : doclet.meta,
see: doclet.see
};
// Add the filtered doclet to the array
filteredDoclets.push(filteredDoclet);
}
else if (doclet.kind == 'class') {
// if the class is not in our map, then we deleted it ourselves -> not available in the editor
if (false == passedClasses.includes(cleanName(doclet.name))) {
continue;
}
const filteredDoclet = {
comment: doclet.comment,
description: doclet.description,
name: cleanName(doclet.name),
longname: cleanName(doclet.longname),
kind: doclet.kind,
scope: "global",
augments: doclet.augments || undefined,
meta: doclet.meta ? {
lineno: doclet.meta.lineno,
columnno: doclet.meta.columnno
} : doclet.meta,
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,
see: doclet.see || undefined
};
filteredDoclets.push(filteredDoclet);
}
else if (doclet.kind == 'typedef') {
const filteredDoclet = {
comment: doclet.comment,
description: doclet.description,
name: cleanName(doclet.name),
longname: cleanName(doclet.longname),
kind: doclet.kind,
scope: "global",
meta: doclet.meta ? {
lineno: doclet.meta.lineno,
columnno: doclet.meta.columnno
} : doclet.meta,
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,
see: doclet.see,
type: doclet.type ? {
names: doclet.type.names,
parsedType: doclet.type.parsedType
} : doclet.type
};
filteredDoclets.push(filteredDoclet);
}
}
// Replace doclets with a filtered array
e.doclets.splice(0, e.doclets.length, ...filteredDoclets);
}
};

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs-forms/apiBuilder.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/pdf/apiBuilder.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs/slide/apiBuilder.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/word/apiBuilder.js"]
},
"plugins": ["./correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,110 +0,0 @@
import os
import subprocess
import json
import argparse
import re
import platform
root = '../../../../..'
# Configuration files
configs = [
"./config/word.json",
"./config/cell.json",
"./config/slide.json",
"./config/forms.json"
]
editors_maps = {
"word": "CDE",
"cell": "CSE",
"slide": "CPE",
"forms": "CFE"
}
def generate(output_dir, md=False):
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_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)
# Append examples to JSON documentation
for config in configs:
editor_name = config.split('/')[-1].replace('.json', '')
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)
# Modify JSON data
for doclet in data:
if 'see' in doclet:
if doclet['see'] is not None:
if editor_name == 'forms':
doclet['see'][0] = doclet['see'][0].replace('{Editor}', 'Word')
else:
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()
# 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
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 for builder 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"
)
args = parser.parse_args()
generate(args.destination)

View File

@ -1,585 +0,0 @@
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"
}
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('<', '&lt;')
.replace('>', '&gt;')
.replace('{', '&#123;')
.replace('}', '&#125;'))
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 + ".&lt;" + ", ".join(generic_args) + "&gt;"
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"&lt;{element}&gt;"
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):
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="../../../../../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")

View File

@ -1,245 +0,0 @@
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"
}
root = '../../../../..'
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):
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="../../../../../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")

View File

@ -1,7 +0,0 @@
{
"dependencies": {
"jsdoc-to-markdown": "7.1.1",
"dmd": "6.1.0",
"handlebars": "4.7.7"
}
}

View File

@ -1,85 +0,0 @@
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);
}
};

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/cell/plugin-events.js"]
},
"plugins": ["../correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/common/base-plugin-events.js"]
},
"plugins": ["../correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs-forms/plugin-events.js"]
},
"plugins": ["../correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

View File

@ -1,16 +0,0 @@
{
"source": {
"include": ["../../../../../sdkjs/slide/plugin-events.js"]
},
"plugins": ["../correct_doclets.js"],
"opts": {
"destination": "./out",
"recurse": true,
"encoding": "utf8"
},
"templates": {
"json": {
"pretty": true
}
}
}

Some files were not shown because too many files have changed in this diff Show More