mirror of
https://github.com/ONLYOFFICE/build_tools.git
synced 2026-04-07 14:06:31 +08:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 55f811af62 | |||
| 057f0bbbf6 | |||
| 67060cc66e | |||
| c5f6c2e02b | |||
| 71b912e7e6 | |||
| 6e7fd50583 | |||
| cf39498098 | |||
| 1f4e593943 | |||
| 3dfd22c735 | |||
| f92fc0f617 | |||
| 0402a5a07a | |||
| dea91ca6f6 | |||
| 4be0e0cbe2 | |||
| 1e8825e15e | |||
| 9d17f87811 | |||
| 2fff3a7391 | |||
| c0bdb1d62b | |||
| 7c97a9b326 | |||
| b33d92a32e | |||
| d480266a5a | |||
| 98af1ed74b | |||
| 9428ce8b33 | |||
| c1dbdc39f1 | |||
| 5d99680cc4 | |||
| 930b11f19e | |||
| 62aa75d82c | |||
| f926970677 | |||
| 4f6908154c | |||
| 151c4e7d2f | |||
| 8adc9021e4 | |||
| 9b97de22df | |||
| 997734860b | |||
| 4473fd7cf9 | |||
| 923d839483 | |||
| 39b1c1e22c | |||
| 849d78fea0 | |||
| 49619cdb40 | |||
| 9bdb69dfa3 | |||
| ceda5ea658 | |||
| ec2d587993 | |||
| 10118f4c68 | |||
| 3cdc164d7f | |||
| b9c9811b9e | |||
| 70bbdfbd43 | |||
| 5dbf27a039 | |||
| 39fb488af8 | |||
| 4866786097 | |||
| 07b1eadc0a | |||
| 9db40b2505 | |||
| 42b57d6b40 | |||
| 506fbd056a | |||
| def11f3134 | |||
| 3285a3e3c5 | |||
| bdcdfa89e7 | |||
| 1835e3ad28 | |||
| 1b33175880 | |||
| 4629471d5b | |||
| a4b29c6acc | |||
| 621b34ffde | |||
| 29ceaa34bf | |||
| 50addf9d18 | |||
| 7269dda75e | |||
| 3f54aec7f8 | |||
| 2d059101ee | |||
| 4dda7dfa7a | |||
| b6d3392571 | |||
| 4001a636db | |||
| cf4c2fc02f | |||
| f94a95df22 | |||
| 7cbaa00356 | |||
| 71cd913944 | |||
| 76fd5a0d37 | |||
| db1b2c01fc | |||
| 9cc6e0b749 | |||
| 8912b82d1f | |||
| d6e215595f | |||
| 6f59b470a3 | |||
| 9241aa8a9b | |||
| 87a7c2922b | |||
| 211348776c | |||
| b2f6b6e2c3 | |||
| 4ea37abdf3 | |||
| ee324a764e | |||
| cee13fbcbe | |||
| 453786b595 | |||
| 9eb7651e84 | |||
| 7b37cc9f83 | |||
| c2a38839dd | |||
| be9f90d220 | |||
| 91937f3d77 | |||
| e70acf9822 | |||
| 243a14ddb9 | |||
| fd7cf76aea | |||
| e48534d14c | |||
| 055ff85f68 | |||
| 12a1765ca0 | |||
| 763dea4889 | |||
| 38a3863213 | |||
| c860de3721 | |||
| 3ce6a41dce | |||
| c69158af8f | |||
| b47b412529 | |||
| 355ae98932 | |||
| 4d812fa6d2 | |||
| ef8153c053 | |||
| 430a9878e5 | |||
| 561c648069 | |||
| f99bcd2ed0 | |||
| df1c566005 | |||
| d548d731ae | |||
| 4e1cfb10b4 | |||
| 4d767c127b | |||
| 71d9e34164 | |||
| d3a2f05945 | |||
| 97b4421e3c | |||
| 73576ff817 | |||
| b4ba33bb69 | |||
| e04df1ba9a | |||
| dd148a105e | |||
| acf75749c2 | |||
| 354e4a6a04 | |||
| b85fb9c07c | |||
| 40b95455a0 | |||
| eef1d728b5 | |||
| cc24ee8e85 | |||
| 62ab1f9935 | |||
| dd26863a2b | |||
| c02a387a64 | |||
| 0fd6852fe8 | |||
| 0dbf009c6b | |||
| 2378bb91fd | |||
| e349f3dba2 | |||
| 559837ee13 | |||
| e700a98963 | |||
| 9635b8c08f | |||
| 878057972b | |||
| 1f7a7fc452 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -15,6 +15,3 @@ tests/puppeteer/package.json
|
||||
tests/puppeteer/package-lock.json
|
||||
scripts/sdkjs_common/jsdoc/node_modules
|
||||
scripts/sdkjs_common/jsdoc/package-lock.json
|
||||
tools/linux/python3/
|
||||
tools/linux/python3.tar.gz
|
||||
tools/linux/sysroot/sysroot_ubuntu_1604
|
||||
|
||||
44
Dockerfile
44
Dockerfile
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:20.04
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ENV TZ=Etc/UTC
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
@ -9,25 +9,37 @@ RUN echo 'keyboard-configuration keyboard-configuration/layoutcode string us' |
|
||||
echo 'keyboard-configuration keyboard-configuration/modelcode string pc105' | debconf-set-selections
|
||||
|
||||
RUN apt-get -y update && \
|
||||
apt-get -y install tar \
|
||||
sudo \
|
||||
wget
|
||||
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.30.0/cmake-3.30.0-linux-x86_64.tar.gz && \
|
||||
tar -xzf cmake-3.30.0-linux-x86_64.tar.gz -C /opt && \
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/cmake /usr/local/bin/cmake && \
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/ctest /usr/local/bin/ctest && \
|
||||
rm cmake-3.30.0-linux-x86_64.tar.gz
|
||||
apt-get -y install sudo \
|
||||
git \
|
||||
git-lfs \
|
||||
curl \
|
||||
wget \
|
||||
p7zip-full
|
||||
|
||||
ADD . /build_tools
|
||||
WORKDIR /build_tools
|
||||
|
||||
RUN mkdir -p /opt/python3 && \
|
||||
wget -P /opt/python3/ https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/python3.tar.gz && \
|
||||
tar -xzf /opt/python3/python3.tar.gz -C /opt/python3 --strip-components=1
|
||||
# Install local Python
|
||||
RUN cd tools/linux && \
|
||||
./python.sh
|
||||
|
||||
ENV PATH="/opt/python3/bin:${PATH}"
|
||||
# Fetch Qt binaries
|
||||
RUN cd tools/linux && \
|
||||
./python3/bin/python3 ./qt_binary_fetch.py amd64
|
||||
|
||||
RUN ln -s /opt/python3/bin/python3.10 /usr/bin/python
|
||||
# Install system dependencies
|
||||
RUN cd tools/linux && \
|
||||
./python3/bin/python3 ./deps.py
|
||||
|
||||
CMD ["sh", "-c", "cd tools/linux && python3 ./automate.py"]
|
||||
# Install CMake
|
||||
RUN cd tools/linux && \
|
||||
./cmake.sh
|
||||
|
||||
# Fetch sysroot
|
||||
RUN cd tools/linux/sysroot && \
|
||||
../python3/bin/python3 ./fetch.py amd64
|
||||
|
||||
ARG BRANCH=master
|
||||
ENV BRANCH=${BRANCH}
|
||||
|
||||
CMD ["sh", "-c", "./tools/linux/python3/bin/python3 ./configure.py --sysroot \"1\" --clean \"0\" --update-light \"1\" --branch \"${BRANCH}\" --update \"1\" --module \"desktop server builder\" --qt-dir \"$(pwd)/tools/linux/qt_build/Qt-5.9.9\" && ./tools/linux/python3/bin/python3 ./make.py"]
|
||||
380
README.md
380
README.md
@ -1,221 +1,218 @@
|
||||
# build_tools
|
||||
<h1>ONLYOFFICE Build Tools</h1>
|
||||
|
||||
## Overview
|
||||
Welcome to the ```build_tools``` repository! This powerful toolkit simplifies the process of compiling [ONLYOFFICE](https://github.com/ONLYOFFICE) products from source on Linux.
|
||||
|
||||
**build_tools** allow you to automatically get and install all the components
|
||||
necessary for the compilation process, all the dependencies required for the
|
||||
**ONLYOFFICE Document Server**, **Document Builder** and **Desktop Editors**
|
||||
correct work, as well as to get the latest version of
|
||||
**ONLYOFFICE products** source code and build all their components.
|
||||
It automatically fetches all the required dependencies and source code to build the latest versions of:
|
||||
|
||||
**Important!** We can only guarantee the correct work of the products built
|
||||
from the `master` branch.
|
||||
* [Docs (Document Server)](https://www.onlyoffice.com/docs?utm_source=github&utm_medium=cpc&utm_campaign=GitHubBuildTools)
|
||||
* [Desktop Editors](https://www.onlyoffice.com/desktop?utm_source=github&utm_medium=cpc&utm_campaign=GitHubBuildTools)
|
||||
* [Document Builder](https://www.onlyoffice.com/document-builder?utm_source=github&utm_medium=cpc&utm_campaign=GitHubBuildTools)
|
||||
|
||||
## How to use - Linux
|
||||
**A quick note:** For the most stable and reliable builds, we strongly recommend compiling from the ```master``` branch of this repository.
|
||||
|
||||
**Note**: The solution has been tested on **Ubuntu 16.04**.
|
||||
## **How do I use it on Linux? 🐧**
|
||||
|
||||
### Installing dependencies
|
||||
>This guide has been tested and verified on **Ubuntu 16.04**.
|
||||
|
||||
You might need to install **Python**, depending on your version of Ubuntu:
|
||||
### **Step 1: Install dependencies**
|
||||
|
||||
First, let's make sure you have **Python** installed, as it's needed to run the build scripts.
|
||||
|
||||
```bash
|
||||
sudo apt-get install -y python
|
||||
```
|
||||
|
||||
### Building ONLYOFFICE products source code
|
||||
### **Step 2: Build the source code**
|
||||
|
||||
1. Clone the build_tools repository:
|
||||
Now, you're ready to build the ONLYOFFICE products.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ONLYOFFICE/build_tools.git
|
||||
1. **Clone the build_tools repository:**
|
||||
|
||||
This command downloads the build tools to your machine using Git:
|
||||
```bash
|
||||
git clone https://github.com/ONLYOFFICE/build_tools.git
|
||||
```
|
||||
|
||||
2. **Navigate to the scripts directory:**
|
||||
```bash
|
||||
cd build_tools/tools/linux
|
||||
```
|
||||
3. **Run the automation script:**
|
||||
|
||||
This is where the magic happens! Running the script without any options will build all three products: Document Server, Document Builder, and Desktop Editors.
|
||||
|
||||
```bash
|
||||
./automate.py
|
||||
```
|
||||
You can also build ONLYOFFICE products separately. Just run the script with the parameter corresponding to the necessary product. For example, to build *Desktop Editors* and *Document Server*
|
||||
```bash
|
||||
./automate.py desktop server
|
||||
```
|
||||
|
||||
**Perfect!** Once the script finishes, you will find the compiled products in the ```./out``` directory.
|
||||
|
||||
## **Advanced options & different workflows 🚀**
|
||||
|
||||
### **How to use Docker**
|
||||
|
||||
If you prefer using Docker, you can build all products inside a container. This is a great way to keep your local system clean.
|
||||
|
||||
1. **Create an output directory:**
|
||||
|
||||
```bash
|
||||
mkdir out
|
||||
```
|
||||
|
||||
2. Go to the `build_tools/tools/linux` directory:
|
||||
2. **Build the Docker image:**
|
||||
|
||||
```bash
|
||||
cd build_tools/tools/linux
|
||||
```bash
|
||||
docker build --tag onlyoffice-document-editors-builder .
|
||||
```
|
||||
|
||||
3. **Run the container to start the build:**
|
||||
|
||||
This command mounts your local out directory into the container, so the final build files will appear on your machine.
|
||||
|
||||
```bash
|
||||
docker run -v $PWD/out:/build_tools/out onlyoffice-document-editors-builder
|
||||
```
|
||||
|
||||
3. Run the `automate.py` script:
|
||||
You've done it! The results will be in the ```./out``` directory you created.
|
||||
|
||||
```bash
|
||||
./automate.py
|
||||
```
|
||||
## **How to build and run the products separately ▶️**
|
||||
|
||||
If you run the script without any parameters this allows to build **ONLYOFFICE
|
||||
Document Server**, **Document Builder** and **Desktop Editors**.
|
||||
Don't need everything? You can save time by building only the products you need. Just add the product name as an argument to the script.
|
||||
|
||||
The result will be available in the `./out` directory.
|
||||
### Need just the [Document Builder](https://github.com/ONLYOFFICE/DocumentBuilder)❓
|
||||
* How to build
|
||||
|
||||
To build **ONLYOFFICE** products separately run the script with the parameter
|
||||
corresponding to the necessary product.
|
||||
```bash
|
||||
./automate.py builder
|
||||
```
|
||||
* How to run
|
||||
```bash
|
||||
cd ../../out/linux_64/onlyoffice/documentbuilder
|
||||
./docbuilder
|
||||
```
|
||||
|
||||
It’s also possible to build several products at once as shown in the example
|
||||
below.
|
||||
### Need just the [Desktop Editors](https://github.com/ONLYOFFICE/DesktopEditors)❓
|
||||
|
||||
**Example**: Building **Desktop Editors** and **Document Server**
|
||||
* How to build
|
||||
```bash
|
||||
./automate.py desktop
|
||||
```
|
||||
* How to run
|
||||
```bash
|
||||
cd ../../out/linux_64/onlyoffice/desktopeditors
|
||||
LD_LIBRARY_PATH=./ ./DesktopEditors
|
||||
```
|
||||
|
||||
### Need just the [Docs (Document Server)](https://github.com/ONLYOFFICE/DocumentServer)❓
|
||||
* How to build
|
||||
```bash
|
||||
./automate.py server
|
||||
```
|
||||
* How to run
|
||||
|
||||
Running the Document Server is a multi-step process because it relies on a few background services. Let's break it down step by step.
|
||||
|
||||
#### **Step 1. Set up dependencies**
|
||||
|
||||
The Document Server needs a few things to run correctly:
|
||||
|
||||
* **NGINX**: Acts as a web server to handle requests.
|
||||
* **PostgreSQL**: Used as the database to store information.
|
||||
* **RabbitMQ**: A message broker that helps different parts of the server communicate.
|
||||
|
||||
Here are the commands to install and configure them.
|
||||
|
||||
#### **Install and configure NGINX**
|
||||
|
||||
1. Install NGINX
|
||||
```bash
|
||||
sudo apt-get install nginx
|
||||
```
|
||||
2. Disable the default NGINX site
|
||||
```bash
|
||||
sudo rm -f /etc/nginx/sites-enabled/default
|
||||
```
|
||||
3. Set up the new website. To do that create the ```/etc/nginx/sites-available/onlyoffice-documentserver``` file with the following contents:
|
||||
|
||||
```bash
|
||||
./automate.py desktop server
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
map $http_upgrade $proxy_connection {
|
||||
default upgrade;
|
||||
"" close;
|
||||
}
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $proxy_connection;
|
||||
proxy_set_header X-Forwarded-Host $the_host;
|
||||
proxy_set_header X-Forwarded-Proto $the_scheme;
|
||||
server {
|
||||
listen 0.0.0.0:80;
|
||||
listen [::]:80 default_server;
|
||||
server_tokens off;
|
||||
rewrite ^\/OfficeWeb(\/apps\/.*)$ /web-apps$1 redirect;
|
||||
location / {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using Docker
|
||||
|
||||
You can also build all **ONLYOFFICE products** at once using Docker.
|
||||
Build the `onlyoffice-document-editors-builder` Docker image using the
|
||||
provided `Dockerfile` and run the corresponding Docker container.
|
||||
|
||||
4. Enable the new site by creating a symbolic link
|
||||
```bash
|
||||
mkdir out
|
||||
docker build --tag onlyoffice-document-editors-builder .
|
||||
docker run -v $PWD/out:/build_tools/out onlyoffice-document-editors-builder
|
||||
sudo ln -s /etc/nginx/sites-available/onlyoffice-documentserver /etc/nginx/sites-enabled/onlyoffice-documentserver
|
||||
```
|
||||
|
||||
The result will be available in the `./out` directory.
|
||||
|
||||
### Building and running ONLYOFFICE products separately
|
||||
|
||||
#### Document Builder
|
||||
|
||||
##### Building Document Builder
|
||||
|
||||
5. Restart NGINX to apply the changes
|
||||
```bash
|
||||
./automate.py builder
|
||||
sudo nginx -s reload
|
||||
```
|
||||
#### **Install and configure PostgreSQL**
|
||||
|
||||
##### Running Document Builder
|
||||
|
||||
```bash
|
||||
cd ../../out/linux_64/onlyoffice/documentbuilder
|
||||
./docbuilder
|
||||
```
|
||||
|
||||
#### Desktop Editors
|
||||
|
||||
##### Building Desktop Editors
|
||||
|
||||
```bash
|
||||
./automate.py desktop
|
||||
```
|
||||
|
||||
##### Running Desktop Editors
|
||||
|
||||
```bash
|
||||
cd ../../out/linux_64/onlyoffice/desktopeditors
|
||||
LD_LIBRARY_PATH=./ ./DesktopEditors
|
||||
```
|
||||
|
||||
#### Document Server
|
||||
|
||||
##### Building Document Server
|
||||
|
||||
```bash
|
||||
./automate.py server
|
||||
```
|
||||
|
||||
##### Installing and configuring Document Server dependencies
|
||||
|
||||
**Document Server** uses **NGINX** as a web server and **PostgreSQL** as a database.
|
||||
**RabbitMQ** is also required for **Document Server** to work correctly.
|
||||
|
||||
###### Installing and configuring NGINX
|
||||
|
||||
1. Install NGINX:
|
||||
|
||||
```bash
|
||||
sudo apt-get install nginx
|
||||
```
|
||||
|
||||
2. Disable the default website:
|
||||
|
||||
```bash
|
||||
sudo rm -f /etc/nginx/sites-enabled/default
|
||||
```
|
||||
|
||||
3. Set up the new website. To do that create the `/etc/nginx/sites-available/onlyoffice-documentserver`
|
||||
file with the following contents:
|
||||
|
||||
```bash
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
map $http_upgrade $proxy_connection {
|
||||
default upgrade;
|
||||
"" close;
|
||||
}
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $proxy_connection;
|
||||
proxy_set_header X-Forwarded-Host $the_host;
|
||||
proxy_set_header X-Forwarded-Proto $the_scheme;
|
||||
server {
|
||||
listen 0.0.0.0:80;
|
||||
listen [::]:80 default_server;
|
||||
server_tokens off;
|
||||
rewrite ^\/OfficeWeb(\/apps\/.*)$ /web-apps$1 redirect;
|
||||
location / {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Add the symlink to the newly created website to the
|
||||
`/etc/nginx/sites-available` directory:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/onlyoffice-documentserver /etc/nginx/sites-enabled/onlyoffice-documentserver
|
||||
```
|
||||
|
||||
5. Restart NGINX to apply the changes:
|
||||
|
||||
```bash
|
||||
sudo nginx -s reload
|
||||
```
|
||||
|
||||
###### Installing and configuring PostgreSQL
|
||||
|
||||
1. Install PostgreSQL:
|
||||
|
||||
1. Install PostgreSQL
|
||||
```bash
|
||||
sudo apt-get install postgresql
|
||||
```
|
||||
|
||||
2. Create the PostgreSQL database and user:
|
||||
|
||||
**Note**: The created database must have **onlyoffice** both for user and password.
|
||||
2. Create a database and user.
|
||||
|
||||
**Note**: The user and password must both be **'onlyoffice'.**
|
||||
```bash
|
||||
sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH PASSWORD 'onlyoffice';"
|
||||
sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice OWNER onlyoffice;"
|
||||
```
|
||||
|
||||
3. Configure the database:
|
||||
|
||||
3. Configure the database:
|
||||
```bash
|
||||
psql -hlocalhost -Uonlyoffice -d onlyoffice -f ../../out/linux_64/onlyoffice/documentserver/server/schema/postgresql/createdb.sql
|
||||
```
|
||||
|
||||
**Note**: Upon that, you will be asked to provide a password for the **onlyoffice**
|
||||
PostgreSQL user. Please enter the **onlyoffice** password.
|
||||
|
||||
###### Installing RabbitMQ
|
||||
Upon that, you will be asked to provide a password for the onlyoffice PostgreSQL user. Please enter the **onlyoffice** password.
|
||||
|
||||
#### **Install RabbitMQ**
|
||||
```bash
|
||||
sudo apt-get install rabbitmq-server
|
||||
```
|
||||
|
||||
###### Generate fonts data
|
||||
Now that you have all the dependencies installed, it's time to generate server files.
|
||||
#### **Step 2. Generate server files**
|
||||
|
||||
Before running the server, you need to generate font and theme data.
|
||||
|
||||
##### **Generate fonts data**
|
||||
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/
|
||||
@ -230,8 +227,7 @@ LD_LIBRARY_PATH=${PWD}/server/FileConverter/bin server/tools/allfontsgen \
|
||||
--use-system="true"
|
||||
```
|
||||
|
||||
###### Generate presentation themes
|
||||
|
||||
##### **Generate presentation themes**
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/
|
||||
LD_LIBRARY_PATH=${PWD}/server/FileConverter/bin server/tools/allthemesgen \
|
||||
@ -240,27 +236,39 @@ LD_LIBRARY_PATH=${PWD}/server/FileConverter/bin server/tools/allthemesgen \
|
||||
--output="${PWD}/sdkjs/common/Images"
|
||||
```
|
||||
|
||||
##### Running Document Server
|
||||
#### **Step 3. Run the Document Server services**
|
||||
|
||||
**Note**: All **Document Server** components run as foreground processes. Thus
|
||||
you need separate terminal consoles to run them or specific tools which will
|
||||
allow to run foreground processes in background mode.
|
||||
All Document Server components run as foreground processes. Thus you need separate terminal consoles to run them or specific tools which will allow to run foreground processes in background mode.
|
||||
|
||||
1. Start the **FileConverter** service:
|
||||
* **Start the FileConverter service:**
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/server/FileConverter
|
||||
LD_LIBRARY_PATH=$PWD/bin \
|
||||
NODE_ENV=development-linux \
|
||||
NODE_CONFIG_DIR=$PWD/../Common/config \
|
||||
./converter
|
||||
```
|
||||
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/server/FileConverter
|
||||
LD_LIBRARY_PATH=$PWD/bin \
|
||||
NODE_ENV=development-linux \
|
||||
NODE_CONFIG_DIR=$PWD/../Common/config \
|
||||
./converter
|
||||
```
|
||||
* **Start the DocService service:**
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/server/DocService
|
||||
NODE_ENV=development-linux \
|
||||
NODE_CONFIG_DIR=$PWD/../Common/config \
|
||||
./docservice
|
||||
```
|
||||
|
||||
2. Start the **DocService** service:
|
||||
## And it's a wrap! 🎉
|
||||
Congratulations! You have successfully used the ```build_tools``` to compile your desired ONLYOFFICE products from the latest source code.
|
||||
|
||||
```bash
|
||||
cd out/linux_64/onlyoffice/documentserver/server/DocService
|
||||
NODE_ENV=development-linux \
|
||||
NODE_CONFIG_DIR=$PWD/../Common/config \
|
||||
./docservice
|
||||
```
|
||||
Everything is now set up. You can go ahead and run your brand-new, self-compiled ONLYOFFICE applications.
|
||||
|
||||
## Need help or have an idea? 💡
|
||||
|
||||
* **🐞 Found a bug?** Please report it by creating an [issue](https://github.com/ONLYOFFICE/build_tools/issues).
|
||||
* **❓ Have a question?** Ask our community and developers on the [ONLYOFFICE Forum](https://community.onlyoffice.com).
|
||||
* **💡 Want to suggest a feature?** Share your ideas on our [feedback platform](https://feedback.onlyoffice.com/forums/966080-your-voice-matters).
|
||||
* **🧑💻 Need help for developers?** Check our [API documentation](https://api.onlyoffice.com/?utm_source=github&utm_medium=cpc&utm_campaign=GitHubBuildTools).
|
||||
|
||||
---
|
||||
|
||||
<p align="center"> Made with ❤️ by the ONLYOFFICE Team </p>
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
# Docker
|
||||
|
||||
This directory containing instruction for developers,
|
||||
who want to change something in sdkjs or web-apps or server module,
|
||||
but don't want to compile pretty compilcated core product to make those changes.
|
||||
This directory contains instructions for developers,
|
||||
who want to change something in sdkjs, web-apps, or the server module,
|
||||
but don't want to compile the complicated core product to make those changes.
|
||||
|
||||
## System requirements
|
||||
|
||||
**Note**: ARM-based architectures are currently **NOT** supported;
|
||||
attempting to run the images on ARM devices may result in startup failures
|
||||
or other runtime issues.
|
||||
|
||||
### Windows
|
||||
|
||||
You need the latest
|
||||
@ -29,22 +25,22 @@ You need the latest
|
||||
[Docker](https://docs.docker.com/engine/install/)
|
||||
version installed.
|
||||
|
||||
## Create develop Docker Images
|
||||
## Create Development Docker Image
|
||||
|
||||
To create a image with the ability to include external non-minified sdkjs code,
|
||||
To create an image with the ability to include external non-minified sdkjs code,
|
||||
use the following commands:
|
||||
|
||||
### Clone development environment to work dir
|
||||
### Clone development environment to the working directory
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ONLYOFFICE/build_tools.git
|
||||
```
|
||||
|
||||
### Modify Docker Images
|
||||
### Build Docker 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.
|
||||
**Note**: Do not prefix the docker command with sudo.
|
||||
[These instructions](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)
|
||||
show how to use docker without sudo.
|
||||
|
||||
```bash
|
||||
cd build_tools/develop
|
||||
@ -54,11 +50,11 @@ docker build --no-cache -t documentserver-develop .
|
||||
|
||||
**Note**: The dot at the end is required.
|
||||
|
||||
**Note**: Sometimes script may fail due to network errors. Just restart it.
|
||||
**Note**: Sometimes the build may fail due to network errors. Just restart it.
|
||||
|
||||
## Clone development modules
|
||||
|
||||
Clone development modules to the work dir
|
||||
Clone development modules to the working directory.
|
||||
|
||||
* `sdkjs` repo is located [here](https://github.com/ONLYOFFICE/sdkjs/)
|
||||
* `web-apps` repo is located [here](https://github.com/ONLYOFFICE/web-apps/)
|
||||
@ -76,43 +72,49 @@ 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
|
||||
The folder `server` is optional.
|
||||
|
||||
**Note**: Run command with the current working directory
|
||||
**Note**: Run the 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
|
||||
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`
|
||||
**Note**: Starting the server with `sdkjs` and `web-apps` takes 15 minutes,
|
||||
or 20 minutes with `server`.
|
||||
|
||||
### docker run on Windows (PowerShell)
|
||||
|
||||
**Note**: Run PowerShell as administrator to fix EACCES error when installing
|
||||
node_modules
|
||||
node_modules.
|
||||
|
||||
run with `sdkjs` and `web-apps`
|
||||
Run with `sdkjs` and `web-apps`
|
||||
|
||||
```bash
|
||||
```powershell
|
||||
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`
|
||||
Or run with `sdkjs`, `web-apps`, and `server`
|
||||
|
||||
```powershell
|
||||
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
|
||||
```
|
||||
|
||||
**Note**: If using Git Bash instead of PowerShell, you may need to quote the paths:
|
||||
|
||||
```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 -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
|
||||
```
|
||||
|
||||
### docker run on Linux or macOS
|
||||
|
||||
run with `sdkjs` and `web-apps`
|
||||
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`
|
||||
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
|
||||
@ -120,93 +122,99 @@ docker run -i -t -p 80:80 --restart=always -e ALLOW_PRIVATE_IP_ADDRESS=true -v $
|
||||
|
||||
## Open editor
|
||||
|
||||
After the server starts successfully, you will see Docker log messages like this
|
||||
After the server starts successfully, you will see Docker log messages like this.
|
||||
|
||||
```bash
|
||||
```text
|
||||
[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)
|
||||
**Note**: Disable **ad blockers** for the localhost page.
|
||||
They may block some scripts (like Analytics.js).
|
||||
|
||||
## Modify sources
|
||||
|
||||
### To change something in `sdkjs` do the following steps
|
||||
### 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)
|
||||
1) Edit the source file. Let's insert an image URL into each open document.
|
||||
The following command inserts (in case of problems, you can replace the 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
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
(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
|
||||
|
||||
**Linux:**
|
||||
```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`
|
||||
**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
|
||||
```
|
||||
|
||||
3)Open new file in browser
|
||||
2) Clear the browser cache or hard reload the page (`Ctrl + Shift + R` or `Cmd + Shift + R` on macOS)
|
||||
|
||||
### To change something in `server` do the following steps
|
||||
3) Open a new file in the browser
|
||||
|
||||
1)Edit source file. Let's send `"Hello World!"`
|
||||
chart message every time a document is opened.
|
||||
Following command inserts
|
||||
### To change something in `server`, do the following steps
|
||||
|
||||
1) Edit the source file. Let's send a `"Hello World!"`
|
||||
chat message every time a document is opened.
|
||||
The 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
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
(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
|
||||
|
||||
**Linux:**
|
||||
```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
|
||||
**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
|
||||
```
|
||||
|
||||
**Note**: Look for ``CONTAINER_ID`` in the result of ``docker ps``.
|
||||
2) Restart the 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
|
||||
3) Open a new file in the browser
|
||||
|
||||
## Start server with additional functionality(addons)
|
||||
## 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
|
||||
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`
|
||||
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
|
||||
node_modules.
|
||||
|
||||
```bash
|
||||
```powershell
|
||||
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 `
|
||||
|
||||
66
linux-start.sh
Normal file
66
linux-start.sh
Normal file
@ -0,0 +1,66 @@
|
||||
sudo apt-get install git curl wget p7zip-full
|
||||
|
||||
sudo apt-get install git-lfs
|
||||
# for old system (ubuntu 16)
|
||||
#curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
|
||||
#sudo apt-get install git-lfs
|
||||
|
||||
# save login
|
||||
git config --global credential.helper store
|
||||
|
||||
# clone build_tools
|
||||
git clone https://git.onlyoffice.com/ONLYOFFICE/build_tools.git
|
||||
|
||||
# deps =========================================
|
||||
|
||||
cd ./build_tools/tools/linux
|
||||
|
||||
# python 3.10
|
||||
./python.sh
|
||||
|
||||
# qt
|
||||
#./python3/bin/python3 ./qt_binary_fetch.py amd64
|
||||
#./python3/bin/python3 ./qt_binary_fetch.py arm64
|
||||
./python3/bin/python3 ./qt_binary_fetch.py all
|
||||
|
||||
# deps
|
||||
./python3/bin/python3 ./deps.py
|
||||
|
||||
# cmake 3.30
|
||||
sudo ./cmake.sh
|
||||
|
||||
cd ../../
|
||||
|
||||
# ==============================================
|
||||
|
||||
# sysroots (IF NEEDED) =========================
|
||||
|
||||
cd ./build_tools/tools/linux/sysroot
|
||||
#./python3/bin/python3 ./fetch.py amd64
|
||||
#./python3/bin/python3 ./fetch.py arm64
|
||||
./../python3/bin/python3 ./fetch.py all
|
||||
cd ../../../
|
||||
|
||||
# ==============================================
|
||||
|
||||
|
||||
# configure ====================================
|
||||
|
||||
./tools/linux/python3/bin/python3 ./configure.py --clean "0" --update-light "1" --update "1" --branch "hotfix/v9.2.1" --module "desktop" --qt-dir "$(pwd)/tools/linux/qt_build/Qt-5.9.9"
|
||||
|
||||
# with sysroot: sysroot "1"
|
||||
|
||||
# ==============================================
|
||||
|
||||
# cross build linux_arm64
|
||||
sudo apt install qemu-user qemu-user-static binfmt-support
|
||||
sudo update-binfmts --enable qemu-aarch64
|
||||
|
||||
# 1) without sysroot
|
||||
#sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
|
||||
#sudo dpkg --add-architecture arm64
|
||||
#sudo apt update
|
||||
#... install all dev packages ...
|
||||
|
||||
# 2) official supported: with sysroot
|
||||
./tools/linux/python3/bin/python3 ./configure.py sysroot "1" #...
|
||||
2
make.py
2
make.py
@ -91,8 +91,6 @@ if config.check_option("module", "desktop"):
|
||||
config.extend_option("config", "updmodule")
|
||||
base.set_env("DESKTOP_URL_UPDATES_MAIN_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/appcast.json")
|
||||
base.set_env("DESKTOP_URL_UPDATES_DEV_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/appcastdev.json")
|
||||
base.set_env("DESKTOP_URL_INSTALL_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/distrib/onlyoffice/<file>")
|
||||
base.set_env("DESKTOP_URL_INSTALL_DEV_CHANNEL", "https://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/onlineinstallerdev/<file>")
|
||||
|
||||
# build
|
||||
build_sln.make()
|
||||
|
||||
194
scripts/base.py
194
scripts/base.py
@ -37,9 +37,11 @@ def is_os_64bit():
|
||||
return platform.machine().endswith('64')
|
||||
|
||||
def is_os_arm():
|
||||
if -1 == platform.machine().find('arm'):
|
||||
return False
|
||||
return True
|
||||
if -1 != platform.machine().lower().find('arm'):
|
||||
return True
|
||||
if -1 != platform.machine().lower().find('aarch64'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_platform():
|
||||
return platform.machine().lower()
|
||||
@ -254,7 +256,10 @@ def delete_dir(path):
|
||||
shutil.rmtree(get_path(path), ignore_errors=True)
|
||||
return
|
||||
|
||||
def copy_lib(src, dst, name):
|
||||
def copy_lib(src_folder, dst, name, subdir=""):
|
||||
src = src_folder
|
||||
if subdir != "":
|
||||
src += ("/" + subdir)
|
||||
if (config.check_option("config", "bundle_dylibs")) and is_dir(src + "/" + name + ".framework"):
|
||||
copy_dir(src + "/" + name + ".framework", dst + "/" + name + ".framework", symlinks=True)
|
||||
|
||||
@ -431,11 +436,46 @@ def cmd_in_dir(directory, prog, args=[], is_no_errors=False):
|
||||
return ret
|
||||
|
||||
def cmd_in_dir_qemu(platform, directory, prog, args=[], is_no_errors=False):
|
||||
if (platform == "linux_arm64"):
|
||||
return cmd_in_dir(directory, "qemu-aarch64", ["-L", "/usr/aarch64-linux-gnu", prog] + args, is_no_errors)
|
||||
if (platform == "linux_arm32"):
|
||||
return cmd_in_dir(directory, "qemu-arm", ["-L", "/usr/arm-linux-gnueabi", prog] + args, is_no_errors)
|
||||
return 0
|
||||
platform_config = {
|
||||
"linux_arm64": {
|
||||
"qemu": "qemu-aarch64",
|
||||
"default_libs": "/usr/aarch64-linux-gnu"
|
||||
},
|
||||
"linux_arm32": {
|
||||
"qemu": "qemu-arm",
|
||||
"default_libs": "/usr/arm-linux-gnueabi"
|
||||
}
|
||||
}
|
||||
|
||||
if platform not in platform_config:
|
||||
return 0
|
||||
|
||||
libs_path = platform_config[platform]["default_libs"]
|
||||
if config.option("sysroot") != "":
|
||||
libs_path = config.option("sysroot_" + platform)
|
||||
|
||||
return cmd_in_dir(directory, platform_config[platform]["qemu"], ["-L", libs_path, prog] + args, is_no_errors)
|
||||
|
||||
def create_qemu_wrapper(binary_path, platform):
|
||||
binary_dir = os.path.dirname(binary_path)
|
||||
binary_name = os.path.basename(binary_path)
|
||||
binary_bin = binary_path + '.bin'
|
||||
sysroot = config.option("sysroot_" + platform)
|
||||
|
||||
if os.path.exists(binary_path):
|
||||
os.rename(binary_path, binary_bin)
|
||||
|
||||
wrapper_content = f'''#!/bin/bash
|
||||
DIR="$(cd "$(dirname "${{BASH_SOURCE[0]}}")" && pwd)"
|
||||
export QEMU_LD_PREFIX={sysroot}
|
||||
exec qemu-aarch64 -L {sysroot} "$DIR/{binary_name}.bin" "$@"
|
||||
'''
|
||||
|
||||
with open(binary_path, 'w') as f:
|
||||
f.write(wrapper_content)
|
||||
|
||||
os.chmod(binary_path, 0o755)
|
||||
return binary_bin
|
||||
|
||||
def cmd_and_return_cwd(prog, args=[], is_no_errors=False):
|
||||
cur_dir = os.getcwd()
|
||||
@ -619,6 +659,7 @@ def get_repositories():
|
||||
result.update(get_server_addons())
|
||||
result["document-server-integration"] = [False, False]
|
||||
result["document-templates"] = [False, False]
|
||||
result["document-formats"] = [False, False]
|
||||
|
||||
get_branding_repositories(result)
|
||||
return result
|
||||
@ -689,18 +730,25 @@ def git_dir():
|
||||
if ("windows" == host_platform()):
|
||||
return run_command("git --info-path")['stdout'] + "/../../.."
|
||||
|
||||
def get_prefix_cross_compiler_arm64():
|
||||
cross_compiler_arm64 = config.option("arm64-toolchain-bin")
|
||||
if is_file(cross_compiler_arm64 + "/aarch64-linux-gnu-g++") and is_file(cross_compiler_arm64 + "/aarch64-linux-gnu-gcc"):
|
||||
return "aarch64-linux-gnu-"
|
||||
if is_file(cross_compiler_arm64 + "/aarch64-unknown-linux-gnu-g++") and is_file(cross_compiler_arm64 + "/aarch64-unknown-linux-gnu-gcc"):
|
||||
return "aarch64-unknown-linux-gnu-"
|
||||
return ""
|
||||
def get_compiler_gcc_prefix(platform):
|
||||
directory = "/usr/bin"
|
||||
|
||||
if config.option("sysroot") != "":
|
||||
use_platform = platform
|
||||
if ("linux_arm64" == platform and not is_os_arm()):
|
||||
use_platform = "linux_64"
|
||||
directory = config.option("sysroot_" + use_platform) + "/usr/bin"
|
||||
|
||||
if ("linux_arm64" == platform and not is_os_arm()):
|
||||
return directory + "/aarch64-linux-gnu-"
|
||||
|
||||
return directory + "/"
|
||||
|
||||
def get_gcc_version():
|
||||
gcc_path = "gcc"
|
||||
# if use sysroot - fix gcc version
|
||||
if config.option("sysroot") != "":
|
||||
gcc_path = config.option("sysroot") + "/usr/bin/gcc"
|
||||
return 5004
|
||||
gcc_path = "gcc"
|
||||
gcc_version_major = 4
|
||||
gcc_version_minor = 0
|
||||
gcc_version_str = run_command(gcc_path + " -dumpfullversion -dumpversion")['stdout']
|
||||
@ -750,13 +798,6 @@ def qt_setup(platform):
|
||||
set_env("QT_QMAKE_ADDON", "-spec win32-arm64-msvc2017")
|
||||
|
||||
set_env("QT_DEPLOY", qt_dir + "/bin")
|
||||
|
||||
if ("linux_arm64" == platform):
|
||||
cross_compiler_arm64 = config.option("arm64-toolchain-bin")
|
||||
if ("" != cross_compiler_arm64):
|
||||
set_env("ARM64_TOOLCHAIN_BIN", cross_compiler_arm64)
|
||||
set_env("ARM64_TOOLCHAIN_BIN_PREFIX", get_prefix_cross_compiler_arm64())
|
||||
|
||||
return qt_dir
|
||||
|
||||
def qt_version():
|
||||
@ -897,29 +938,34 @@ def qt_copy_lib(lib, dir):
|
||||
def _check_icu_common(dir, out):
|
||||
isExist = False
|
||||
for file in glob.glob(dir + "/libicu*"):
|
||||
isExist = True
|
||||
break
|
||||
|
||||
# Skip static libraries
|
||||
if not file.endswith('.a'):
|
||||
isExist = True
|
||||
break
|
||||
if isExist:
|
||||
copy_files(dir + "/libicui18n*", out)
|
||||
copy_files(dir + "/libicuuc*", out)
|
||||
copy_files(dir + "/libicudata*", out)
|
||||
|
||||
# Copy only shared libraries (skip .a files)
|
||||
for pattern in ["/libicui18n*", "/libicuuc*", "/libicudata*"]:
|
||||
for file in glob.glob(dir + pattern):
|
||||
if not file.endswith('.a'):
|
||||
copy_file(file, out)
|
||||
return isExist
|
||||
|
||||
def qt_copy_icu(out):
|
||||
def qt_copy_icu(out, platform):
|
||||
tests = [get_env("QT_DEPLOY") + "/../lib"]
|
||||
prefix = ""
|
||||
postfixes = [""]
|
||||
|
||||
# TODO add for linux arm desktop build
|
||||
if config.option("sysroot") != "":
|
||||
prefix = config.option("sysroot")
|
||||
if config.option("sysroot_" + platform) != "":
|
||||
prefix = config.option("sysroot_" + platform)
|
||||
else:
|
||||
prefix = ""
|
||||
|
||||
postfixes += ["/x86_64-linux-gnu"]
|
||||
postfixes += ["/i386-linux-gnu"]
|
||||
|
||||
if ("linux_64" == platform):
|
||||
postfixes += ["/x86_64-linux-gnu"]
|
||||
elif ("linux_arm64" == platform):
|
||||
postfixes += ["/aarch64-linux-gnu"]
|
||||
elif ("linux_32" == platform):
|
||||
postfixes += ["/i386-linux-gnu"]
|
||||
|
||||
for postfix in postfixes:
|
||||
tests += [prefix + "/lib" + postfix]
|
||||
@ -1319,7 +1365,10 @@ def mac_change_rpath_library(lib_name, old, new):
|
||||
|
||||
def mac_correct_rpath_binary(path, libs):
|
||||
# if framework are built, instead of correcting lib paths add `@loader_path` to rpaths with `mac_add_loader_path_to_rpath()`
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
try:
|
||||
if config.check_option("config", "bundle_dylibs"):
|
||||
return
|
||||
except:
|
||||
return
|
||||
|
||||
for lib in libs:
|
||||
@ -1349,7 +1398,9 @@ def mac_correct_rpath_x2t(dir):
|
||||
mac_correct_rpath_library("OFDFile", ["UnicodeConverter", "kernel", "graphics", "PdfFile"])
|
||||
mac_correct_rpath_library("DocxRenderer", ["UnicodeConverter", "kernel", "graphics"])
|
||||
mac_correct_rpath_library("IWorkFile", ["UnicodeConverter", "kernel"])
|
||||
mac_correct_rpath_library("HWPFile", ["UnicodeConverter", "kernel", "graphics"])
|
||||
mac_correct_rpath_library("HWPFile", ["UnicodeConverter", "kernel", "graphics", "StarMathConverter"])
|
||||
mac_correct_rpath_library("StarMathConverter", ["kernel"])
|
||||
mac_correct_rpath_library("ooxmlsignature", ["kernel"])
|
||||
|
||||
def correct_core_executable(name, libs):
|
||||
cmd("chmod", ["-v", "+x", name])
|
||||
@ -1357,7 +1408,7 @@ def mac_correct_rpath_x2t(dir):
|
||||
mac_correct_rpath_binary(name, mac_icu_libs + libs)
|
||||
return
|
||||
|
||||
correct_core_executable("x2t", ["UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "doctrenderer", "DocxRenderer", "IWorkFile", "HWPFile"])
|
||||
correct_core_executable("x2t", ["UnicodeConverter", "kernel", "kernel_network", "graphics", "PdfFile", "XpsFile", "OFDFile", "DjVuFile", "HtmlFile2", "Fb2File", "EpubFile", "doctrenderer", "DocxRenderer", "IWorkFile", "HWPFile", "StarMathConverter", "ooxmlsignature"])
|
||||
if is_file("./allfontsgen"):
|
||||
correct_core_executable("allfontsgen", ["UnicodeConverter", "kernel", "graphics"])
|
||||
if is_file("./allthemesgen"):
|
||||
@ -1590,6 +1641,12 @@ def hack_xcode_ios():
|
||||
file.write(filedata)
|
||||
return
|
||||
|
||||
def find_ios_sdk(sdk_name):
|
||||
return run_command("xcrun --sdk " + sdk_name + " --show-sdk-path")['stdout']
|
||||
|
||||
def find_xcode_toolchain(sdk_name):
|
||||
return run_command("xcrun --sdk " + sdk_name + " --show-toolchain-path")['stdout']
|
||||
|
||||
def find_mac_sdk_version():
|
||||
sdk_dir = run_command("xcode-select -print-path")['stdout']
|
||||
sdk_dir = os.path.join(sdk_dir, "Platforms/MacOSX.platform/Developer/SDKs")
|
||||
@ -1664,6 +1721,9 @@ def replaceFileLicence(path, license):
|
||||
def copy_v8_files(core_dir, deploy_dir, platform, is_xp=False):
|
||||
if (-1 != config.option("config").find("use_javascript_core")):
|
||||
return
|
||||
if (0 == platform.find("mac")) and not (config.check_option("config", "use_v8")):
|
||||
return
|
||||
|
||||
directory_v8 = core_dir + "/Common/3dParty"
|
||||
|
||||
if is_xp:
|
||||
@ -1887,25 +1947,38 @@ def check_module_version(actual_version, clear_func):
|
||||
clear_func()
|
||||
return
|
||||
|
||||
|
||||
def set_sysroot_env():
|
||||
def set_sysroot_env(platform):
|
||||
global ENV_BEFORE_SYSROOT
|
||||
ENV_BEFORE_SYSROOT = dict(os.environ)
|
||||
if "linux" == host_platform() and config.option("sysroot") != "":
|
||||
os.environ['PATH'] = config.option("sysroot") + "/usr/bin:" + get_env("PATH")
|
||||
os.environ['LD_LIBRARY_PATH'] = config.get_custom_sysroot_lib()
|
||||
os.environ['QMAKE_CUSTOM_SYSROOT'] = config.option("sysroot")
|
||||
os.environ['PKG_CONFIG_PATH'] = config.get_custom_sysroot_lib() + "/pkgconfig"
|
||||
os.environ['CC'] = config.get_custom_sysroot_bin() + "/gcc"
|
||||
os.environ['CXX'] = config.get_custom_sysroot_bin() + "/g++"
|
||||
os.environ['CFLAGS'] = "--sysroot=" + config.option("sysroot")
|
||||
os.environ['CXXFLAGS'] = "--sysroot=" + config.option("sysroot")
|
||||
check_python()
|
||||
|
||||
|
||||
if "linux" != host_platform():
|
||||
return
|
||||
if config.option("sysroot") == "":
|
||||
return
|
||||
|
||||
path = config.option("sysroot_" + platform)
|
||||
sysroot_path_bin = config.get_custom_sysroot_bin(platform)
|
||||
compiler_gcc_prefix = get_compiler_gcc_prefix(platform)
|
||||
|
||||
os.environ['PATH'] = sysroot_path_bin + ":" + get_env("PATH")
|
||||
os.environ['LD_LIBRARY_PATH'] = config.get_custom_sysroot_lib(platform)
|
||||
|
||||
os.environ['CC'] = compiler_gcc_prefix + "gcc"
|
||||
os.environ['CXX'] = compiler_gcc_prefix + "g++"
|
||||
os.environ['AR'] = compiler_gcc_prefix + "ar"
|
||||
os.environ['RANLIB'] = compiler_gcc_prefix + "ranlib"
|
||||
|
||||
os.environ['CFLAGS'] = "--sysroot=" + path
|
||||
os.environ['CXXFLAGS'] = "--sysroot=" + path
|
||||
os.environ['LDFLAGS'] = "--sysroot=" + path
|
||||
|
||||
check_python()
|
||||
return
|
||||
|
||||
def restore_sysroot_env():
|
||||
os.environ.clear()
|
||||
os.environ.update(ENV_BEFORE_SYSROOT)
|
||||
|
||||
|
||||
def check_python():
|
||||
if ("linux" != host_platform()):
|
||||
return
|
||||
@ -1914,8 +1987,9 @@ def check_python():
|
||||
|
||||
if not is_dir(directory + "/python3"):
|
||||
download('https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/python3.tar.gz', directory + "/python3.tar.gz")
|
||||
cmd("tar", ["xfz", directory + "/python3.tar.gz", "-C", directory])
|
||||
cmd("ln", ["-s", directory_bin + "/python3", directory_bin + "/python"])
|
||||
download('https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/extract.sh', directory + "/extract.sh")
|
||||
cmd_in_dir(directory, "chmod", ["+x", "./extract.sh"])
|
||||
cmd_in_dir(directory, "./extract.sh")
|
||||
directory_bin = directory_bin.replace(" ", "\\ ")
|
||||
os.environ["PATH"] = directory_bin + os.pathsep + os.environ["PATH"]
|
||||
return
|
||||
@ -1993,7 +2067,7 @@ def create_artifacts_qemu_win_arm():
|
||||
if config.option("qemu-win-arm64-dir") == "":
|
||||
print("For deploying win_arm64 on non arm host you should provide qemu-win-arm64-dir. More info in tools/win/qemu/README.md")
|
||||
return
|
||||
|
||||
|
||||
old_curr_dir = os.path.abspath(os.curdir)
|
||||
qemu_dir = os.path.abspath(config.option("qemu-win-arm64-dir"))
|
||||
|
||||
@ -2008,7 +2082,7 @@ def create_x2t_js_cache(dir, product, platform):
|
||||
doctrenderer_lib = "libdoctrenderer.dylib" if is_file(dir + "/libdoctrenderer.dylib") else "doctrenderer.framework/doctrenderer"
|
||||
if os.path.getsize(dir + "/" + doctrenderer_lib) < 5*1024*1024:
|
||||
return
|
||||
|
||||
|
||||
if ((platform == "linux_arm64") and not is_os_arm()):
|
||||
cmd_in_dir_qemu(platform, dir, "./x2t", ["-create-js-snapshots"], True)
|
||||
return
|
||||
|
||||
@ -11,6 +11,7 @@ def make():
|
||||
|
||||
git_dir = base.get_script_dir() + "/../.."
|
||||
server_dir = base.get_script_dir() + "/../../server"
|
||||
server_admin_panel_dir = base.get_script_dir() + "/../../server-admin-panel"
|
||||
branding_dir = server_dir + "/branding"
|
||||
|
||||
if("" != config.option("branding")):
|
||||
@ -49,10 +50,11 @@ 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 + "/DocService", "pkg", [".", "-t", pkg_target, "--options", "max_old_space_size=6144", "-o", "docservice"])
|
||||
base.cmd_in_dir(server_dir + "/FileConverter", "pkg", [".", "-t", pkg_target, "-o", "converter"])
|
||||
base.cmd_in_dir(server_dir + "/Metrics", "pkg", [".", "-t", pkg_target, "-o", "metrics"])
|
||||
base.cmd_in_dir(server_dir + "/AdminPanel/server", "pkg", [".", "-t", pkg_target, "-o", "adminpanel"])
|
||||
if "server-admin-panel" in base.get_server_addons() and base.is_exist(server_admin_panel_dir):
|
||||
base.cmd_in_dir(server_admin_panel_dir + "/server", "pkg", [".", "-t", pkg_target, "-o", "adminpanel"])
|
||||
|
||||
example_dir = base.get_script_dir() + "/../../document-server-integration/web/documentserver-example/nodejs"
|
||||
base.delete_dir(example_dir + "/node_modules")
|
||||
@ -66,8 +68,10 @@ def build_server_with_addons():
|
||||
for addon in addons:
|
||||
if (addon):
|
||||
addon_dir = base.get_script_dir() + "/../../" + addon
|
||||
if (base.is_exist(addon_dir)):
|
||||
if (base.is_exist(addon_dir + "/package.json")):
|
||||
base.print_info("npm ci: " + addon)
|
||||
base.cmd_in_dir(addon_dir, "npm", ["ci"])
|
||||
base.print_info("npm run build: " + addon)
|
||||
base.cmd_in_dir(addon_dir, "npm", ["run", "build"])
|
||||
|
||||
def build_server_develop():
|
||||
|
||||
@ -63,12 +63,6 @@ def parse():
|
||||
if not check_option("platform", "win_64"):
|
||||
options["platform"] = "win_64 " + options["platform"]
|
||||
|
||||
if ("linux" == host_platform) and check_option("platform", "linux_arm64") and not base.is_os_arm():
|
||||
if not check_option("platform", "linux_64"):
|
||||
# linux_64 binaries need only for desktop
|
||||
if check_option("module", "desktop"):
|
||||
options["platform"] = "linux_64 " + options["platform"]
|
||||
|
||||
if check_option("platform", "xp") and ("windows" == host_platform):
|
||||
options["platform"] += " win_64_xp win_32_xp"
|
||||
|
||||
@ -93,17 +87,17 @@ def parse():
|
||||
options["sysroot"] = ""
|
||||
elif options["sysroot"] == "1":
|
||||
dst_dir = os.path.abspath(base.get_script_dir(__file__) + '/../tools/linux/sysroot')
|
||||
custom_sysroot = dst_dir + '/sysroot_ubuntu_1604'
|
||||
options["sysroot"] = custom_sysroot
|
||||
if not os.path.isdir(custom_sysroot):
|
||||
print("Sysroot is not found, downloading...")
|
||||
sysroot_url = 'https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/sysroot/sysroot_ubuntu_1604.tar.xz'
|
||||
base.download(sysroot_url, dst_dir + '/sysroot_ubuntu_1604.tar.xz')
|
||||
os.mkdir(custom_sysroot)
|
||||
print("Unpacking...")
|
||||
base.cmd2('tar', ['-xf', dst_dir + '/sysroot_ubuntu_1604.tar.xz', '-C', dst_dir])
|
||||
if os.path.exists(dst_dir + '/sysroot_ubuntu_1604.tar.xz'):
|
||||
os.remove(dst_dir + '/sysroot_ubuntu_1604.tar.xz')
|
||||
dst_dir_amd64 = dst_dir + "/ubuntu16-amd64-sysroot"
|
||||
dst_dir_arm64 = dst_dir + "/ubuntu16-arm64-sysroot"
|
||||
if not base.is_dir(dst_dir_amd64) or not base.is_dir(dst_dir_arm64):
|
||||
base.cmd_in_dir(dst_dir, "python3", ["./fetch.py", "all"])
|
||||
options["sysroot_linux_64"] = dst_dir_amd64
|
||||
options["sysroot_linux_arm64"] = dst_dir_arm64
|
||||
else:
|
||||
# specific sysroot => one platform for build!
|
||||
options["sysroot"] = "1"
|
||||
options["sysroot_linux_64"] = options["sysroot"]
|
||||
options["sysroot_linux_arm64"] = options["sysroot"]
|
||||
|
||||
if is_cef_107():
|
||||
extend_option("config", "cef_version_107")
|
||||
@ -131,12 +125,6 @@ def parse():
|
||||
if not "sdkjs-plugin-server" in options:
|
||||
options["sdkjs-plugin-server"] = "default"
|
||||
|
||||
if not "arm64-toolchain-bin" in options:
|
||||
if not "sysroot" in options:
|
||||
options["arm64-toolchain-bin"] = "/usr/bin"
|
||||
else:
|
||||
options["arm64-toolchain-bin"] = get_custom_sysroot_bin()
|
||||
|
||||
if check_option("platform", "ios"):
|
||||
if not check_option("config", "no_bundle_xcframeworks"):
|
||||
if not check_option("config", "bundle_xcframeworks"):
|
||||
@ -236,13 +224,25 @@ def is_mobile_platform():
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_custom_sysroot_bin():
|
||||
return option("sysroot") + "/usr/bin"
|
||||
def get_custom_sysroot_bin(platform):
|
||||
use_platform = platform
|
||||
if "linux_arm64" == platform and not base.is_os_arm():
|
||||
# use cross compiler
|
||||
use_platform = "linux_64"
|
||||
|
||||
# todo 32bit support?
|
||||
def get_custom_sysroot_lib():
|
||||
if base.is_os_64bit():
|
||||
return option("sysroot") + "/usr/lib/x86_64-linux-gnu"
|
||||
return option("sysroot_" + use_platform) + "/usr/bin"
|
||||
|
||||
def get_custom_sysroot_lib(platform, isNatural=False):
|
||||
use_platform = platform
|
||||
if "linux_arm64" == platform and not base.is_os_arm() and not isNatural:
|
||||
# use cross compiler
|
||||
use_platform = "linux_64"
|
||||
|
||||
if ("linux_64" == use_platform):
|
||||
return option("sysroot_linux_64") + "/usr/lib/x86_64-linux-gnu"
|
||||
if ("linux_arm64" == use_platform):
|
||||
return option("sysroot_linux_arm64") + "/usr/lib/aarch64-linux-gnu"
|
||||
return ""
|
||||
|
||||
def parse_defaults():
|
||||
defaults_path = base.get_script_dir() + "/../defaults"
|
||||
|
||||
@ -138,14 +138,14 @@ def make():
|
||||
if (-1 != config.option("platform").find("android")) and not base.is_dir("../build/android"):
|
||||
boost_qt.make(os.getcwd(), ["filesystem", "system", "date_time", "regex"])
|
||||
|
||||
if (-1 != config.option("platform").find("mac")) and not base.is_dir("../build/mac_64"):
|
||||
if config.check_option("platform", "mac_64") and not base.is_dir("../build/mac_64"):
|
||||
boost_qt.make(os.getcwd(), ["filesystem", "system", "date_time", "regex"], "mac_64")
|
||||
directory_build = base_dir + "/build/mac_64/lib"
|
||||
base.delete_file(directory_build + "/libboost_system.a")
|
||||
base.delete_file(directory_build + "/libboost_system.dylib")
|
||||
base.copy_files(directory_build + "/mac_64/*.a", directory_build)
|
||||
|
||||
if (-1 != config.option("platform").find("mac_arm64")) and not base.is_dir("../build/mac_arm64"):
|
||||
if config.check_option("platform", "mac_arm64") and not base.is_dir("../build/mac_arm64"):
|
||||
boost_qt.make(os.getcwd(), ["filesystem", "system", "date_time", "regex"], "mac_arm64")
|
||||
directory_build = base_dir + "/build/mac_arm64/lib"
|
||||
base.delete_file(directory_build + "/libboost_system.a")
|
||||
|
||||
@ -14,18 +14,8 @@ def make(src_dir, modules, build_platform="android", qmake_addon=""):
|
||||
|
||||
print("boost-headers...")
|
||||
|
||||
# for b2 checks
|
||||
if config.option("sysroot") != "":
|
||||
base.set_sysroot_env()
|
||||
b2_addon = "cflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
b2_addon = "cxxflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
b2_addon = "linkflags=\"--sysroot=" + config.option("sysroot") + "\""
|
||||
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=system"])
|
||||
base.cmd("./b2", ["--prefix=./../build/" + build_platform, "headers", "install", b2_addon])
|
||||
|
||||
if config.option("sysroot") != "":
|
||||
base.restore_sysroot_env()
|
||||
base.cmd("./bootstrap.sh", ["--with-libraries=system"])
|
||||
base.cmd("./b2", ["--prefix=./../build/" + build_platform, "headers", "install"])
|
||||
|
||||
for module in modules:
|
||||
print("boost-module: " + module + " ...")
|
||||
|
||||
@ -21,7 +21,7 @@ def make():
|
||||
os.chdir(base_dir)
|
||||
|
||||
base.check_module_version("2", clear_module)
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp", "linux_64", "linux_32", "mac_64", "mac_arm64", "win_arm64"]
|
||||
platforms = ["win_64", "win_32", "win_64_xp", "win_32_xp", "linux_64", "linux_32", "mac_64", "mac_arm64", "win_arm64", "linux_arm64"]
|
||||
|
||||
for platform in platforms:
|
||||
if not config.check_option("platform", platform):
|
||||
|
||||
@ -21,31 +21,11 @@ IOS_CMAKE_TOOLCHAIN_FILE = base.get_script_dir() + "/../../core/Common/3dParty/h
|
||||
ANDROID_CMAKE_TOOLCHAIN_FILE = base.get_env("ANDROID_NDK_ROOT") + "/build/cmake/android.toolchain.cmake"
|
||||
|
||||
# linux arm64 cmake toolchain
|
||||
LINUX_ARM64_CMAKE_TOOLCHAIN_FILE = base.get_script_dir() + "/../tools/linux/arm/cross_arm64/linux-arm64.toolchain.cmake"
|
||||
|
||||
LINUX_SYSTEM_AARCH64_TOOLCHAIN_FILE = base.get_script_dir() + "/../tools/linux/sysroot/system-aarch64.toolchain.cmake"
|
||||
LINUX_CUSTOM_SYSROOT_TOOLCHAIN_FILE = base.get_script_dir() + "/../tools/linux/sysroot/custom-sysroot.toolchain.cmake"
|
||||
|
||||
OLD_ENV = dict()
|
||||
|
||||
# get custom sysroot vars as str
|
||||
def setup_custom_sysroot_env() -> str:
|
||||
env_vars = []
|
||||
env_vars += ['LD_LIBRARY_PATH=\"' + config.get_custom_sysroot_lib() + "\""]
|
||||
env_vars += ['PATH=\"' + config.option("sysroot") + "/usr/bin:" + base.get_env("PATH") + "\""]
|
||||
env_vars += ['CC=\"' + config.get_custom_sysroot_bin() + "/gcc\""]
|
||||
env_vars += ['CXX=\"' + config.get_custom_sysroot_bin() + "/g++\""]
|
||||
env_vars += ['AR=\"' + config.get_custom_sysroot_bin() + "/ar\""]
|
||||
env_vars += ['RABLIB=\"' + config.get_custom_sysroot_bin() + "/ranlib\""]
|
||||
env_vars += ['CFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
env_vars += ['CXXFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
env_vars += ['LDFLAGS=\"' + "--sysroot=" + config.option("sysroot") + "\""]
|
||||
|
||||
env_str = ""
|
||||
for env_var in env_vars:
|
||||
env_str += env_var + " "
|
||||
|
||||
return env_str
|
||||
|
||||
def get_vs_version():
|
||||
vs_version = "14 2015"
|
||||
if config.option("vs-version") == "2019":
|
||||
@ -90,10 +70,14 @@ def build_with_cmake(platform, cmake_args, build_type):
|
||||
cmake_args_ext += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11", "-DCMAKE_OSX_ARCHITECTURES=x86_64"]
|
||||
elif platform == "mac_arm64":
|
||||
cmake_args_ext += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0", "-DCMAKE_OSX_ARCHITECTURES=arm64"]
|
||||
elif platform == "linux_arm64":
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_ARM64_CMAKE_TOOLCHAIN_FILE]
|
||||
elif config.option("sysroot") != "":
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_CUSTOM_SYSROOT_TOOLCHAIN_FILE] # force use custom CXXFLAGS with Release/Debug build
|
||||
# force use custom CXXFLAGS with Release/Debug build
|
||||
if (platform == "linux_64"):
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_CUSTOM_SYSROOT_TOOLCHAIN_FILE]
|
||||
else:
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_SYSTEM_AARCH64_TOOLCHAIN_FILE]
|
||||
elif platform == "linux_arm64" and not base.is_os_arm():
|
||||
cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + LINUX_SYSTEM_AARCH64_TOOLCHAIN_FILE]
|
||||
# IOS
|
||||
elif "ios" in platform:
|
||||
cmake_args_ext = [
|
||||
@ -127,16 +111,20 @@ def build_with_cmake(platform, cmake_args, build_type):
|
||||
cmake_args_ext += get_cmake_args_android("x86_64", "21")
|
||||
|
||||
# env setup for custom sysroot
|
||||
env_str = setup_custom_sysroot_env() if config.option("sysroot") != "" else ""
|
||||
if config.option("sysroot") != "":
|
||||
base.set_sysroot_env(platform)
|
||||
|
||||
# run cmake
|
||||
base.cmd(env_str + "cmake", cmake_args + cmake_args_ext)
|
||||
base.cmd("cmake", cmake_args + cmake_args_ext)
|
||||
|
||||
# build
|
||||
if "Unix Makefiles" in cmake_args_ext:
|
||||
base.cmd(env_str + "make", ["-j4"])
|
||||
base.cmd("make", ["-j4"])
|
||||
else:
|
||||
base.cmd("cmake", ["--build", ".", "--config", build_type])
|
||||
|
||||
if config.option("sysroot") != "":
|
||||
base.restore_sysroot_env()
|
||||
return
|
||||
|
||||
# general make function that calls `build_func` callback for configured platform(s) with specified cmake arguments
|
||||
|
||||
@ -35,7 +35,7 @@ def make():
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
|
||||
base.check_module_version("7", clear_module)
|
||||
base.check_module_version("8", clear_module)
|
||||
|
||||
if (-1 != config.option("platform").find("android")):
|
||||
icu_android.make()
|
||||
@ -136,13 +136,15 @@ def make():
|
||||
base.cmd(command_configure, ["Linux", "--prefix=" + base_dir + "/icu/cross_build_install"])
|
||||
base.replaceInFile("./../source/icudefs.mk.in", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)", "LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS) " + command_compile_addon)
|
||||
else:
|
||||
base.set_sysroot_env()
|
||||
base.set_sysroot_env("linux_64")
|
||||
sysroot_path = config.option("sysroot_linux_64")
|
||||
sysroot_path_bin = config.get_custom_sysroot_bin("linux_64")
|
||||
base.cmd_exe("./../source/configure", ["--prefix=" + base_dir + "/icu/cross_build_install",
|
||||
"CC=" + config.get_custom_sysroot_bin() + "/gcc", "CXX=" + config.get_custom_sysroot_bin() + "/g++",
|
||||
"AR=" + config.get_custom_sysroot_bin() + "/ar", "RANLIB=" + config.get_custom_sysroot_bin() + "/ranlib",
|
||||
"CFLAGS=--sysroot=" + config.option("sysroot"),
|
||||
"CXXFLAGS=--sysroot=" + config.option("sysroot") + " " + command_compile_addon,
|
||||
"LDFLAGS=--sysroot=" + config.option("sysroot")])
|
||||
"CC=" + sysroot_path_bin + "/gcc", "CXX=" + sysroot_path_bin + "/g++",
|
||||
"AR=" + sysroot_path_bin + "/ar", "RANLIB=" + sysroot_path_bin + "/ranlib",
|
||||
"CFLAGS=--sysroot=" + sysroot_path,
|
||||
"CXXFLAGS=--sysroot=" + sysroot_path + " " + command_compile_addon,
|
||||
"LDFLAGS=--sysroot=" + sysroot_path])
|
||||
|
||||
if "" == config.option("sysroot"):
|
||||
base.cmd("make", ["-j4"])
|
||||
@ -161,9 +163,11 @@ def make():
|
||||
if config.check_option("platform", "linux_arm64") and not base.is_dir(base_dir + "/linux_arm64") and not base.is_os_arm():
|
||||
base.create_dir(base_dir + "/icu/linux_arm64")
|
||||
os.chdir(base_dir + "/icu/linux_arm64")
|
||||
base_arm_tool_dir = config.option('arm64-toolchain-bin') + '/' + base.get_prefix_cross_compiler_arm64()
|
||||
compiler_gcc_prefix = base.get_compiler_gcc_prefix("linux_arm64")
|
||||
if config.option("sysroot") != "":
|
||||
base.set_sysroot_env("linux_arm64")
|
||||
base.cmd("./../source/configure", ["--host=arm-linux", "--prefix=" + base_dir + "/icu/linux_arm64_install", "--with-cross-build=" + base_dir + "/icu/cross_build",
|
||||
"CC=" + base_arm_tool_dir + "gcc", "CXX=" + base_arm_tool_dir + "g++", "AR=" + base_arm_tool_dir + "ar", "RANLIB=" + base_arm_tool_dir + "ranlib"])
|
||||
"CC=" + compiler_gcc_prefix + "gcc", "CXX=" + compiler_gcc_prefix + "g++", "AR=" + compiler_gcc_prefix + "ar", "RANLIB=" + compiler_gcc_prefix + "ranlib"])
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"], True)
|
||||
base.create_dir(base_dir + "/linux_arm64")
|
||||
@ -171,6 +175,8 @@ def make():
|
||||
base.copy_file(base_dir + "/icu/linux_arm64_install/lib/libicudata.so." + icu_major + "." + icu_minor, base_dir + "/linux_arm64/build/libicudata.so." + icu_major)
|
||||
base.copy_file(base_dir + "/icu/linux_arm64_install/lib/libicuuc.so." + icu_major + "." + icu_minor, base_dir + "/linux_arm64/build/libicuuc.so." + icu_major)
|
||||
base.copy_dir(base_dir + "/icu/linux_arm64_install/include", base_dir + "/linux_arm64/build/include")
|
||||
if config.option("sysroot") != "":
|
||||
base.restore_sysroot_env()
|
||||
|
||||
os.chdir("../..")
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ if not base.is_dir(current_dir + "/mac_cross_64"):
|
||||
old_env = change_icu_defs("x86_64")
|
||||
|
||||
base.cmd("../icu/source/runConfigureICU", ["MacOSX",
|
||||
"--prefix=" + current_dir + "/mac_cross_64", "--enable-static"])
|
||||
"--prefix=" + current_dir + "/mac_64_install", "--enable-static"])
|
||||
|
||||
base.cmd("make", ["-j4"])
|
||||
base.cmd("make", ["install"], True)
|
||||
@ -58,7 +58,7 @@ addon = []
|
||||
if not base.is_os_arm():
|
||||
addon = ["--host=aarch64-apple-darwin"]
|
||||
|
||||
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm_64",
|
||||
base.cmd("./configure", ["--prefix=" + current_dir + "/mac_arm64_install",
|
||||
"--with-cross-build=" + current_dir + "/mac_cross_64", "--enable-static", "VERBOSE=1"] + addon)
|
||||
|
||||
base.cmd("make", ["-j4"])
|
||||
@ -80,25 +80,26 @@ base.create_dir(current_dir + "/mac_64/build")
|
||||
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")
|
||||
base.copy_dir(current_dir + "/mac_64_install/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")
|
||||
base.copy_file(current_dir + "/mac_64_install/lib/libicudata." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_64/build/libicudata." + icu_major + ".dylib")
|
||||
base.copy_file(current_dir + "/mac_64_install/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_file(current_dir + "/mac_64_install/lib/libicudata.a", current_dir + "/mac_64/build")
|
||||
base.copy_file(current_dir + "/mac_64_install/lib/libicui18n.a", current_dir + "/mac_64/build")
|
||||
base.copy_file(current_dir + "/mac_64_install/lib/libicuuc.a", current_dir + "/mac_64/build")
|
||||
|
||||
base.copy_dir(current_dir + "/mac_arm_64/include", current_dir + "/mac_arm64/build/include")
|
||||
base.copy_dir(current_dir + "/mac_arm64_install/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")
|
||||
base.copy_file(current_dir + "/mac_arm64_install/lib/libicudata." + icu_major + "." + icu_minor + ".dylib", current_dir + "/mac_arm64/build/libicudata." + icu_major + ".dylib")
|
||||
base.copy_file(current_dir + "/mac_arm64_install/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.copy_file(current_dir + "/mac_arm64_install/lib/libicudata.a", current_dir + "/mac_arm64/build")
|
||||
base.copy_file(current_dir + "/mac_arm64_install/lib/libicui18n.a", current_dir + "/mac_arm64/build")
|
||||
base.copy_file(current_dir + "/mac_arm64_install/lib/libicuuc.a", current_dir + "/mac_arm64/build")
|
||||
|
||||
base.delete_dir(current_dir + "/mac_cross_64")
|
||||
base.delete_dir(current_dir + "/mac_arm_64")
|
||||
base.delete_dir(current_dir + "/mac_64_install")
|
||||
base.delete_dir(current_dir + "/mac_arm64_install")
|
||||
|
||||
os.chdir(current_dir_old)
|
||||
|
||||
@ -22,7 +22,7 @@ def make(use_gperf = True):
|
||||
base_dir = base.get_script_dir() + "/../../core/Common/3dParty/apple"
|
||||
|
||||
os.chdir(base_dir)
|
||||
base.check_module_version("3", clear_module)
|
||||
base.check_module_version("4", clear_module)
|
||||
os.chdir(old_cur_dir)
|
||||
|
||||
cmd_args = ["fetch.py"]
|
||||
@ -35,4 +35,5 @@ def make(use_gperf = True):
|
||||
|
||||
if __name__ == '__main__':
|
||||
# manual compile
|
||||
make(False)
|
||||
make(False)
|
||||
|
||||
|
||||
@ -99,34 +99,35 @@ def make():
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden")
|
||||
else:
|
||||
base.replaceInFile("./Makefile", "CROSS_COMPILE=", "CROSS_COMPILE=" + config.get_custom_sysroot_bin() + "/")
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot"))
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot"))
|
||||
base.replaceInFile("./Makefile", "CROSS_COMPILE=", "CROSS_COMPILE=" + config.get_custom_sysroot_bin("linux_64") + "/")
|
||||
base.replaceInFile("./Makefile", "CFLAGS=-Wall -O3", "CFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot_linux_64"))
|
||||
base.replaceInFile("./Makefile", "CXXFLAGS=-Wall -O3", "CXXFLAGS=-Wall -O3 -fvisibility=hidden --sysroot=" + config.option("sysroot_linux_64"))
|
||||
|
||||
if config.option("sysroot") == "":
|
||||
base.cmd("make", [])
|
||||
base.cmd("make", ["install"])
|
||||
base.cmd("make", ["clean"], True)
|
||||
else:
|
||||
base.set_sysroot_env()
|
||||
base.set_sysroot_env("linux_64")
|
||||
base.cmd_exe("make", [])
|
||||
base.cmd_exe("make", ["install"])
|
||||
base.cmd_exe("make", ["clean"], True)
|
||||
base.restore_sysroot_env()
|
||||
|
||||
if (-1 != config.option("platform").find("linux_arm64")) and not base.is_dir("../build/linux_arm64"):
|
||||
if ("x86_64" != platform.machine()):
|
||||
if (base.is_os_arm()):
|
||||
base.copy_dir("../build/linux_64", "../build/linux_arm64")
|
||||
else:
|
||||
cross_compiler_arm64 = config.option("arm64-toolchain-bin")
|
||||
if ("" == cross_compiler_arm64):
|
||||
cross_compiler_arm64 = "/usr/bin"
|
||||
cross_compiler_arm64_prefix = cross_compiler_arm64 + "/" + base.get_prefix_cross_compiler_arm64()
|
||||
base.cmd("./Configure", ["linux-aarch64", "--cross-compile-prefix=" + cross_compiler_arm64_prefix, "enable-md2", "no-shared", "no-asm", "no-tests", "--prefix=" + old_cur_dir + "/build/linux_arm64", "--openssldir=" + old_cur_dir + "/build/linux_arm64"])
|
||||
if config.option("sysroot") != "":
|
||||
base.set_sysroot_env("linux_arm64")
|
||||
base.cmd("/usr/bin/perl", ["./Configure", "linux-aarch64", "enable-md2", "no-shared", "no-asm", "no-tests", "--prefix=" + old_cur_dir + "/build/linux_arm64", "--openssldir=" + old_cur_dir + "/build/linux_arm64"])
|
||||
#base.cmd("./Configure", ["linux-aarch64", "enable-md2", "no-shared", "no-asm", "no-tests", "--prefix=" + old_cur_dir + "/build/linux_arm64", "--openssldir=" + old_cur_dir + "/build/linux_arm64"])
|
||||
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", [], True)
|
||||
base.cmd("make", ["install"], True)
|
||||
if config.option("sysroot") != "":
|
||||
base.restore_sysroot_env()
|
||||
|
||||
if (-1 != config.option("platform").find("mac")) and not base.is_dir("../build/mac_64"):
|
||||
base.cmd("./Configure", ["enable-md2", "no-shared", "no-asm", "darwin64-x86_64-cc", "--prefix=" + old_cur_dir + "/build/mac_64", "--openssldir=" + old_cur_dir + "/build/mac_64", "-mmacosx-version-min=10.11"])
|
||||
|
||||
@ -33,7 +33,7 @@ def make():
|
||||
|
||||
old_cur = os.getcwd()
|
||||
os.chdir(base_dir)
|
||||
base.common_check_version("socketio", "1", clean)
|
||||
base.common_check_version("socketio", "2", clean)
|
||||
os.chdir(old_cur)
|
||||
|
||||
if not base.is_dir(base_dir + "/socket.io-client-cpp"):
|
||||
|
||||
@ -44,14 +44,9 @@ def is_xp_platform():
|
||||
return False
|
||||
|
||||
def is_use_clang():
|
||||
gcc_version = base.get_gcc_version()
|
||||
|
||||
is_clang = "false"
|
||||
if config.option("sysroot") == "" and (gcc_version >= 6000 or "1" == config.option("use-clang")):
|
||||
is_clang = "true"
|
||||
|
||||
print("gcc version: " + str(gcc_version) + ", use clang:" + is_clang)
|
||||
return is_clang
|
||||
if config.option("sysroot") == "" and "1" == config.option("use-clang"):
|
||||
return "true"
|
||||
return "false"
|
||||
|
||||
def make():
|
||||
if not is_main_platform():
|
||||
@ -235,8 +230,7 @@ def make_xp():
|
||||
base.replaceInFile("depot_tools/cipd.ps1", "windows-386", "windows-amd64")
|
||||
|
||||
# old variant
|
||||
#path_to_python2 = "/depot_tools/win_tools-2_7_13_chromium7_bin/python/bin"
|
||||
path_to_python2 = "/depot_tools/bootstrap-2@3_8_10_chromium_23_bin/python/bin"
|
||||
path_to_python2 = "/depot_tools/bootstrap-2@3_11_8_chromium_35_bin/python/bin"
|
||||
os.environ["PATH"] = os.pathsep.join([base_dir + "/depot_tools",
|
||||
base_dir + path_to_python2,
|
||||
config.option("vs-path") + "/../Common7/IDE",
|
||||
|
||||
@ -7,6 +7,25 @@ import base
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def clean():
|
||||
if base.is_dir("depot_tools"):
|
||||
base.delete_dir_with_access_error("depot_tools")
|
||||
base.delete_dir("depot_tools")
|
||||
if base.is_dir("v8"):
|
||||
base.delete_dir_with_access_error("v8")
|
||||
base.delete_dir("v8")
|
||||
if base.is_exist("./.gclient"):
|
||||
base.delete_file("./.gclient")
|
||||
if base.is_exist("./.gclient_entries"):
|
||||
base.delete_file("./.gclient_entries")
|
||||
if base.is_exist("./.gclient_previous_sync_commits"):
|
||||
base.delete_file("./.gclient_previous_sync_commits")
|
||||
if base.is_exist("./.gcs_entries"):
|
||||
base.delete_file("./.gcs_entries")
|
||||
if base.is_exist("./.cipd"):
|
||||
base.delete_dir("./.cipd")
|
||||
return
|
||||
|
||||
def change_bootstrap():
|
||||
base.move_file("./depot_tools/bootstrap/manifest.txt", "./depot_tools/bootstrap/manifest.txt.bak")
|
||||
content = "# changed by build_tools\n\n"
|
||||
@ -34,6 +53,31 @@ def change_bootstrap():
|
||||
base.writeFile("./depot_tools/bootstrap/manifest.txt", content)
|
||||
return
|
||||
|
||||
def is_ubuntu_24_or_higher():
|
||||
try:
|
||||
with open('/etc/os-release') as f:
|
||||
for line in f:
|
||||
if line.startswith('VERSION_ID='):
|
||||
version = line.split('=')[1].strip().strip('"')
|
||||
return float(version) >= 24
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
def fix_ubuntu24():
|
||||
#if not is_ubuntu_24_or_higher():
|
||||
# return
|
||||
|
||||
if "" == config.option("sysroot"):
|
||||
return
|
||||
|
||||
old_cur = os.getcwd()
|
||||
os.chdir("third_party/llvm-build/Release+Asserts/lib")
|
||||
base.cmd("mv", ["libstdc++.so.6", "libstdc++.so.6.old"])
|
||||
base.cmd("ln", ["-s", "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", "libstdc++.so.6"])
|
||||
os.chdir(old_cur)
|
||||
return
|
||||
|
||||
def make_args(args, platform, is_64=True, is_debug=False):
|
||||
args_copy = args[:]
|
||||
if is_64:
|
||||
@ -47,7 +91,6 @@ def make_args(args, platform, is_64=True, is_debug=False):
|
||||
args_copy = args[:]
|
||||
args_copy.append("target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("v8_target_cpu=\\\"arm64\\\"")
|
||||
args_copy.append("use_sysroot=true")
|
||||
|
||||
if (platform == "win_arm64"):
|
||||
args_copy = args[:]
|
||||
@ -65,8 +108,26 @@ def make_args(args, platform, is_64=True, is_debug=False):
|
||||
linux_clang = False
|
||||
if platform == "linux":
|
||||
if "" != config.option("sysroot"):
|
||||
args_copy.append("use_sysroot=false")
|
||||
args_copy.append("use_sysroot=true")
|
||||
args_copy.append("is_clang=false")
|
||||
if is_ubuntu_24_or_higher():
|
||||
args_copy.append("use_gold=false")
|
||||
args_copy.append("sysroot=\\\"" + config.option("sysroot_linux_64") + "\\\"")
|
||||
args_copy.append("target_sysroot=\\\"" + config.option("sysroot_linux_64") + "\\\"")
|
||||
else:
|
||||
args_copy.append("is_clang=true")
|
||||
if "1" == config.option("use-clang"):
|
||||
linux_clang = True
|
||||
else:
|
||||
args_copy.append("use_sysroot=false")
|
||||
|
||||
if platform == "linux_arm64":
|
||||
if "" != config.option("sysroot"):
|
||||
args_copy.append("use_sysroot=true")
|
||||
if is_ubuntu_24_or_higher():
|
||||
args_copy.append("use_gold=false")
|
||||
#args_copy.append("sysroot=\\\"" + config.option("sysroot_linux_64") + "\\\"")
|
||||
args_copy.append("target_sysroot=\\\"" + config.option("sysroot_linux_arm64") + "\\\"")
|
||||
else:
|
||||
args_copy.append("is_clang=true")
|
||||
if "1" == config.option("use-clang"):
|
||||
@ -78,6 +139,9 @@ def make_args(args, platform, is_64=True, is_debug=False):
|
||||
if (platform == "windows"):
|
||||
args_copy.append("is_clang=false")
|
||||
|
||||
if (platform == "mac") and base.is_os_arm():
|
||||
args_copy.append("host_cpu=\\\"x64\\\"")
|
||||
|
||||
if linux_clang != True:
|
||||
args_copy.append("use_custom_libcxx=false")
|
||||
|
||||
@ -150,6 +214,8 @@ def make():
|
||||
base.cmd("git", ["config", "--global", "http.postBuffer", "157286400"], True)
|
||||
|
||||
os.chdir(base_dir)
|
||||
base.common_check_version("v8", "1", clean)
|
||||
|
||||
if not base.is_dir("depot_tools"):
|
||||
base.cmd("git", ["clone", "https://chromium.googlesource.com/chromium/tools/depot_tools.git"])
|
||||
change_bootstrap()
|
||||
@ -173,6 +239,9 @@ def make():
|
||||
base.cmd("./depot_tools/gclient", ["sync", "-r", v8_branch_version], True)
|
||||
base.cmd("gclient", ["sync", "--force"], True)
|
||||
base.copy_dir("./v8/third_party_new/ninja", "./v8/third_party/ninja")
|
||||
if ("linux" == base.host_platform()):
|
||||
if not base.is_file("./depot_tools/python3_bin_reldir.txt"):
|
||||
base.cmd_in_dir("./depot_tools", "./ensure_bootstrap", [], True)
|
||||
|
||||
if ("windows" == base.host_platform()):
|
||||
base.replaceInFile("v8/build/config/win/BUILD.gn", ":static_crt", ":dynamic_crt")
|
||||
@ -202,6 +271,9 @@ def make():
|
||||
base.replaceInFile("v8/third_party/jinja2/tests.py", "from collections import Mapping", "try:\n from collections.abc import Mapping\nexcept ImportError:\n from collections import Mapping")
|
||||
|
||||
os.chdir("v8")
|
||||
|
||||
is_ubuntu24 = is_ubuntu_24_or_higher()
|
||||
fix_ubuntu24()
|
||||
|
||||
gn_args = ["v8_static_library=true",
|
||||
"is_component_build=false",
|
||||
@ -211,17 +283,17 @@ def make():
|
||||
|
||||
if config.check_option("platform", "linux_64"):
|
||||
if config.option("sysroot") != "":
|
||||
src_replace = "config(\"compiler\") {\n asmflags = []\n cflags = []\n cflags_c = []\n cflags_cc = []\n cflags_objc = []\n cflags_objcc = []\n ldflags = []"
|
||||
dst_replace = "config(\"compiler\") {\n asmflags = []\n cflags = [\"--sysroot=" + config.option("sysroot") + "\"]" + "\n cflags_c = []\n cflags_cc = [\"--sysroot=" + config.option("sysroot") + "\"]" + "\n cflags_objc = []\n cflags_objcc = []\n ldflags = [\"--sysroot=" + config.option("sysroot") + "\"]"
|
||||
base.replaceInFile("build/config/compiler/BUILD.gn", src_replace, dst_replace)
|
||||
sysroot_path = config.option("sysroot_linux_64")
|
||||
sysroot_path_bin = config.get_custom_sysroot_bin("linux_64")
|
||||
|
||||
src_replace = "gcc_toolchain(\"x64\") {\n cc = \"gcc\"\n cxx = \"g++\""
|
||||
dst_replace = "gcc_toolchain(\"x64\") {\n cc = \""+ config.get_custom_sysroot_bin() + "/gcc\"\n cxx = \"" + config.get_custom_sysroot_bin() + "/g++\""
|
||||
base.replaceInFile("build/toolchain/linux/BUILD.gn", src_replace, dst_replace)
|
||||
|
||||
old_env = dict(os.environ)
|
||||
base.set_sysroot_env()
|
||||
base.set_sysroot_env("linux_64")
|
||||
|
||||
pkg_old = os.environ.get("PKG_CONFIG_PATH", "")
|
||||
os.environ["PKG_CONFIG_PATH"] = sysroot_path + "/usr/lib/x86_64-linux-gnu/pkgconfig:" + sysroot_path + "/usr/lib/pkgconfig:" + sysroot_path + "/usr/share/pkgconfig"
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_64", make_args(gn_args, "linux")], False)
|
||||
os.environ["PKG_CONFIG_PATH"] = pkg_old
|
||||
|
||||
base.cmd2("ninja", ["-C", "out.gn/linux_64"], False)
|
||||
base.restore_sysroot_env()
|
||||
else:
|
||||
@ -235,7 +307,13 @@ def make():
|
||||
|
||||
if config.check_option("platform", "linux_arm64"):
|
||||
base.cmd("build/linux/sysroot_scripts/install-sysroot.py", ["--arch=arm64"], False)
|
||||
|
||||
sysroot_path = config.option("sysroot_linux_64")
|
||||
pkg_old = os.environ.get("PKG_CONFIG_PATH", "")
|
||||
os.environ["PKG_CONFIG_PATH"] = sysroot_path + "/usr/lib/x86_64-linux-gnu/pkgconfig:" + sysroot_path + "/usr/lib/pkgconfig:" + sysroot_path + "/usr/share/pkgconfig"
|
||||
base.cmd2("gn", ["gen", "out.gn/linux_arm64", make_args(gn_args, "linux_arm64", False)])
|
||||
os.environ["PKG_CONFIG_PATH"] = pkg_old
|
||||
|
||||
base.cmd("ninja", ["-C", "out.gn/linux_arm64"])
|
||||
|
||||
if config.check_option("platform", "mac_64"):
|
||||
|
||||
@ -47,6 +47,8 @@ def make():
|
||||
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_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "StarMathConverter")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "ooxmlsignature", "xp" if isWindowsXP else "")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", root_dir + "/cmap.bin")
|
||||
|
||||
if ("ios" == platform):
|
||||
|
||||
@ -25,6 +25,7 @@ def make():
|
||||
|
||||
platform = native_platform
|
||||
platform_postfix = platform + base.qt_dst_postfix()
|
||||
isWindowsXP = False if (-1 == native_platform.find("_xp")) else True
|
||||
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "kernel")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "kernel_network")
|
||||
@ -42,6 +43,8 @@ def make():
|
||||
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_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "StarMathConverter")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, archive_dir, "ooxmlsignature", "xp" if isWindowsXP else "")
|
||||
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")
|
||||
|
||||
|
||||
@ -72,6 +72,8 @@ def make():
|
||||
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(build_libraries_path, root_dir + "/converter", "StarMathConverter")
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "ooxmlsignature", "xp" if isWindowsXP else "")
|
||||
|
||||
if ("ios" == platform):
|
||||
base.copy_lib(build_libraries_path, root_dir + "/converter", "x2t")
|
||||
@ -137,7 +139,6 @@ def make():
|
||||
|
||||
# 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")
|
||||
if (0 != platform.find("mac")):
|
||||
base.copy_lib(build_libraries_path + ("/xp" if isWindowsXP else ""), root_dir, "qtascdocumentscore")
|
||||
@ -178,7 +179,7 @@ def make():
|
||||
base.qt_copy_lib("Qt5DBus", root_dir)
|
||||
base.qt_copy_lib("Qt5X11Extras", root_dir)
|
||||
base.qt_copy_lib("Qt5XcbQpa", root_dir)
|
||||
base.qt_copy_icu(root_dir)
|
||||
base.qt_copy_icu(root_dir, platform)
|
||||
if not base.check_congig_option_with_platfom(platform, "libvlc"):
|
||||
base.copy_files(base.get_env("QT_DEPLOY") + "/../lib/libqgsttools_p.so*", root_dir)
|
||||
|
||||
@ -186,8 +187,6 @@ def make():
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/projicons/" + apps_postfix + "/projicons.exe", root_dir + "/DesktopEditors.exe")
|
||||
if not isWindowsXP:
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/update-daemon/" + apps_postfix + "/updatesvc.exe", root_dir + "/updatesvc.exe")
|
||||
else:
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/extras/online-installer/" + apps_postfix + "/online-installer.exe", root_dir + "/online-installer.exe")
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/" + apps_postfix + "/DesktopEditors.exe", root_dir + "/editors.exe")
|
||||
base.copy_file(git_dir + "/desktop-apps/win-linux/res/icons/desktopeditors.ico", root_dir + "/app.ico")
|
||||
elif (0 == platform.find("linux")):
|
||||
@ -244,9 +243,11 @@ def make():
|
||||
#base.copy_dir(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins/encrypt/ui/engine/database/{9AB4BBA8-A7E5-48D5-B683-ECE76A020BB1}", root_dir + "/editors/sdkjs-plugins/{9AB4BBA8-A7E5-48D5-B683-ECE76A020BB1}")
|
||||
base.copy_sdkjs_plugin(git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins", root_dir + "/editors/sdkjs-plugins", "sendto", True)
|
||||
|
||||
isUseAgent = False
|
||||
isUseAgent = True
|
||||
if isWindowsXP:
|
||||
isUseAgent = False
|
||||
if (0 == platform.find("mac")) and (config.check_option("config", "use_v8")):
|
||||
isUseAgent = False
|
||||
|
||||
if (isUseAgent):
|
||||
agent_plugin_dir = git_dir + "/desktop-sdk/ChromiumBasedEditors/plugins/ai-agent"
|
||||
@ -315,8 +316,24 @@ def make():
|
||||
themes_params = []
|
||||
if ("" != config.option("themesparams")):
|
||||
themes_params = ["--params=\"" + config.option("themesparams") + "\""]
|
||||
base.cmd_exe(root_dir + "/converter/allfontsgen", ["--use-system=\"1\"", "--input=\"" + root_dir + "/fonts\"", "--input=\"" + git_dir + "/core-fonts\"", "--allfonts=\"" + root_dir + "/converter/AllFonts.js\"", "--selection=\"" + root_dir + "/converter/font_selection.bin\""], True)
|
||||
base.cmd_exe(root_dir + "/converter/allthemesgen", ["--converter-dir=\"" + root_dir + "/converter\"", "--src=\"" + root_dir + "/editors/sdkjs/slide/themes\"", "--allfonts=\"AllFonts.js\"", "--output=\"" + root_dir + "/editors/sdkjs/common/Images\""] + themes_params, True)
|
||||
|
||||
params_allfontsgen = ["--use-system=\"1\"", "--input=\"" + root_dir + "/fonts\"", "--input=\"" + git_dir + "/core-fonts\"", "--allfonts=\"" + root_dir + "/converter/AllFonts.js\"", "--selection=\"" + root_dir + "/converter/font_selection.bin\""]
|
||||
params_allthemesgen = ["--converter-dir=\"" + root_dir + "/converter\"", "--src=\"" + root_dir + "/editors/sdkjs/slide/themes\"", "--allfonts=\"AllFonts.js\"", "--output=\"" + root_dir + "/editors/sdkjs/common/Images\""] + themes_params
|
||||
if (0 == platform.find("linux_arm") and not base.is_os_arm()):
|
||||
x2t_origin = ""
|
||||
if (config.option("sysroot") != ""):
|
||||
x2t_origin = base.create_qemu_wrapper(root_dir + "/converter/x2t", platform)
|
||||
|
||||
base.cmd_in_dir_qemu(platform, root_dir + "/converter", "./allfontsgen", params_allfontsgen, True)
|
||||
base.cmd_in_dir_qemu(platform, root_dir + "/converter", "./allthemesgen", params_allthemesgen, True)
|
||||
|
||||
if "" != x2t_origin:
|
||||
base.delete_file(root_dir + "/converter/x2t")
|
||||
base.move_file(x2t_origin, root_dir + "/converter/x2t")
|
||||
else:
|
||||
base.cmd_exe(root_dir + "/converter/allfontsgen", params_allfontsgen, True)
|
||||
base.cmd_exe(root_dir + "/converter/allthemesgen", params_allthemesgen, True)
|
||||
|
||||
base.delete_file(root_dir + "/converter/AllFonts.js")
|
||||
base.delete_file(root_dir + "/converter/font_selection.bin")
|
||||
base.delete_file(root_dir + "/converter/fonts.log")
|
||||
@ -328,4 +345,4 @@ def make():
|
||||
if not isUseJSC:
|
||||
base.delete_file(root_dir + "/editors/sdkjs/slide/sdk-all.cache")
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
@ -65,6 +65,8 @@ def make():
|
||||
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_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "StarMathConverter")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, root_dir, "ooxmlsignature")
|
||||
base.copy_file(git_dir + "/sdkjs/pdf/src/engine/cmap.bin", root_dir + "/cmap.bin")
|
||||
|
||||
if (0 == platform.find("win") or 0 == platform.find("linux") or 0 == platform.find("mac")):
|
||||
|
||||
@ -41,6 +41,7 @@ def make():
|
||||
|
||||
build_server_dir = root_dir + '/server'
|
||||
server_dir = base.get_script_dir() + "/../../server"
|
||||
server_admin_panel_dir = base.get_script_dir() + "/../../server-admin-panel"
|
||||
|
||||
base.create_dir(build_server_dir + '/DocService')
|
||||
|
||||
@ -58,13 +59,14 @@ def make():
|
||||
base.create_dir(build_server_dir + '/Metrics/node_modules/modern-syslog/build/Release')
|
||||
base.copy_file(server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node", build_server_dir + "/Metrics/node_modules/modern-syslog/build/Release/core.node")
|
||||
|
||||
# AdminPanel server part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/server')
|
||||
base.copy_exe(server_dir + "/AdminPanel/server", build_server_dir + '/AdminPanel/server', "adminpanel")
|
||||
if "server-admin-panel" in base.get_server_addons() and base.is_exist(server_admin_panel_dir):
|
||||
# AdminPanel server part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/server')
|
||||
base.copy_exe(server_admin_panel_dir + "/server", build_server_dir + '/AdminPanel/server', "adminpanel")
|
||||
|
||||
# AdminPanel client part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/client/build')
|
||||
base.copy_dir(server_dir + '/AdminPanel/client/build', build_server_dir + '/AdminPanel/client/build')
|
||||
# AdminPanel client part
|
||||
base.create_dir(build_server_dir + '/AdminPanel/client/build')
|
||||
base.copy_dir(server_admin_panel_dir + '/client/build', build_server_dir + '/AdminPanel/client/build')
|
||||
|
||||
qt_dir = base.qt_setup(native_platform)
|
||||
platform = native_platform
|
||||
@ -93,6 +95,8 @@ def make():
|
||||
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_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "StarMathConverter")
|
||||
base.copy_lib(core_build_dir + "/lib/" + platform_postfix, converter_dir, "ooxmlsignature")
|
||||
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")
|
||||
|
||||
@ -179,6 +183,12 @@ def make():
|
||||
base.copy_dir(document_templates_files + '/new', document_templates + '/new')
|
||||
base.copy_dir(document_templates_files + '/sample', document_templates + '/sample')
|
||||
|
||||
#document-formats
|
||||
document_formats_files = server_dir + '/../document-formats'
|
||||
document_formats = build_server_dir + '/../document-formats'
|
||||
base.create_dir(document_formats)
|
||||
base.copy_file(document_formats_files + '/onlyoffice-docs-formats.json', document_formats + '/onlyoffice-docs-formats.json')
|
||||
|
||||
#license
|
||||
license_file1 = server_dir + '/LICENSE.txt'
|
||||
license_file2 = server_dir + '/3rd-Party.txt'
|
||||
|
||||
@ -111,7 +111,8 @@ def check_dependencies():
|
||||
if (host_platform == 'windows'):
|
||||
checksResult.append(check_nodejs())
|
||||
|
||||
if (config.option("sql-type") == 'mysql' and host_platform == 'windows'):
|
||||
sql_type = config.option("sql-type")
|
||||
if (sql_type == 'mysql' and host_platform == 'windows'):
|
||||
checksResult.append(check_mysqlServer())
|
||||
else:
|
||||
checksResult.append(check_postgreSQL())
|
||||
@ -300,9 +301,21 @@ def check_rabbitmq():
|
||||
print('RabbitMQ is installed')
|
||||
return dependence
|
||||
elif (host_platform == 'linux'):
|
||||
result = base.run_command('service rabbitmq-server status')['stdout']
|
||||
if (result != ''):
|
||||
print('Installed RabbitMQ is valid')
|
||||
result = ''
|
||||
|
||||
# Prefer systemctl for systemd
|
||||
systemctl_result = base.run_command('systemctl status rabbitmq-server')
|
||||
if systemctl_result['returncode'] == 0 and systemctl_result['stdout']:
|
||||
result = systemctl_result['stdout']
|
||||
|
||||
# Fallback to service for SysV
|
||||
if result == '':
|
||||
command_result = base.run_command('service rabbitmq-server status')
|
||||
if command_result['returncode'] == 0 and command_result['stdout']:
|
||||
result = command_result['stdout']
|
||||
|
||||
if result != '':
|
||||
print('RabbitMQ is installed')
|
||||
return dependence
|
||||
|
||||
print('RabbitMQ not found')
|
||||
@ -517,8 +530,9 @@ def check_mysqlServer():
|
||||
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):
|
||||
connectionResult = base.run_command(connectionString)
|
||||
expected_port = config.option("db-port")
|
||||
if (connectionResult['stdout'].find('port') != -1 and connectionResult['stdout'].find(expected_port) != -1):
|
||||
print('MySQL configuration is valid')
|
||||
dependence.sqlPath = 'mysql'
|
||||
return dependence
|
||||
@ -533,13 +547,15 @@ def check_mysqlServer():
|
||||
continue
|
||||
|
||||
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):
|
||||
mysql_bin_path = get_mysql_path_to_bin(info['Location'])
|
||||
connectionResult = base.run_command_in_dir(mysql_bin_path, connectionString)
|
||||
|
||||
expected_port = config.option("db-port")
|
||||
if (connectionResult['stdout'].find('port') != -1 and connectionResult['stdout'].find(expected_port) != -1):
|
||||
print(mysql_full_name + 'configuration is valid')
|
||||
dependence.sqlPath = info['Location']
|
||||
return dependence
|
||||
print(mysql_full_name + 'configuration is not valid:' + connectionResult)
|
||||
print(mysql_full_name + 'configuration is not valid')
|
||||
# if path exists, then further removal and installation fails(according to startup statistics). it is better to fix issue manually.
|
||||
return dependence
|
||||
|
||||
@ -632,8 +648,8 @@ def get_postrgre_path_to_bin(postgrePath = ''):
|
||||
return postgrePath
|
||||
def get_postgreLoginSrting(userName):
|
||||
if (host_platform == 'windows'):
|
||||
return 'psql -U' + userName + ' '
|
||||
return 'PGPASSWORD="' + config.option("db-pass") + '" psql -U' + userName + ' -hlocalhost '
|
||||
return 'psql -U ' + userName + ' -h localhost '
|
||||
return 'PGPASSWORD="' + config.option("db-pass") + '" psql -U ' + userName + ' -h localhost '
|
||||
def get_postgreSQLInfoByFlag(flag):
|
||||
arrInfo = []
|
||||
|
||||
@ -667,9 +683,10 @@ def check_postgreSQL():
|
||||
|
||||
if (host_platform == 'linux'):
|
||||
result = os.system(postgreLoginSrt + ' -c "\q"')
|
||||
connectionResult = base.run_command(connectionString)['stdout']
|
||||
connectionResult = base.run_command(connectionString)
|
||||
expected_port = config.option("db-port")
|
||||
|
||||
if (result != 0 or connectionResult.find(config.option("db-port")) == -1):
|
||||
if (result != 0 or connectionResult['stdout'].find(expected_port) == -1):
|
||||
print('Valid PostgreSQL not found!')
|
||||
dependence.append_install('PostgreSQL')
|
||||
dependence.append_uninstall('PostgreSQL')
|
||||
@ -680,18 +697,20 @@ def check_postgreSQL():
|
||||
|
||||
arrInfo = get_postgreSQLInfo()
|
||||
base.set_env('PGPASSWORD', config.option("db-pass"))
|
||||
|
||||
for info in arrInfo:
|
||||
if (base.is_dir(info['Location']) == False):
|
||||
continue
|
||||
|
||||
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):
|
||||
postgre_bin_path = get_postrgre_path_to_bin(info['Location'])
|
||||
connectionResult = base.run_command_in_dir(postgre_bin_path, connectionString)
|
||||
|
||||
expected_port = config.option("db-port")
|
||||
if (connectionResult['stdout'].find(expected_port) != -1):
|
||||
print(postgre_full_name + 'configuration is valid')
|
||||
dependence.sqlPath = info['Location']
|
||||
return dependence
|
||||
print(postgre_full_name + 'configuration is not valid')
|
||||
|
||||
print('Valid PostgreSQL not found')
|
||||
|
||||
@ -704,6 +723,8 @@ def check_postgreSQL():
|
||||
return dependence
|
||||
def check_postgreConfig(postgrePath = ''):
|
||||
result = True
|
||||
base.print_info('Checking PostgreSQL configuration')
|
||||
|
||||
if (host_platform == 'windows'):
|
||||
base.set_env('PGPASSWORD', config.option("db-pass"))
|
||||
|
||||
@ -711,53 +732,78 @@ def check_postgreConfig(postgrePath = ''):
|
||||
dbUser = config.option("db-user")
|
||||
dbName = config.option("db-name")
|
||||
dbPass = config.option("db-pass")
|
||||
|
||||
postgre_path_to_bin = get_postrgre_path_to_bin(postgrePath)
|
||||
postgreLoginRoot = get_postgreLoginSrting(rootUser)
|
||||
postgreLoginDbUser = get_postgreLoginSrting(dbUser)
|
||||
creatdb_path = base.get_script_dir() + "/../../server/schema/postgresql/createdb.sql"
|
||||
|
||||
if (base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + ' -c "\du ' + dbUser + '"')['stdout'].find(dbUser) != -1):
|
||||
print('User ' + dbUser + ' is exist')
|
||||
# Check if user exists
|
||||
user_check_result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + ' -c "\du ' + dbUser + '"')
|
||||
|
||||
if (user_check_result['stdout'].find(dbUser) != -1):
|
||||
# User exists, check password
|
||||
if (os.system(postgreLoginDbUser + '-c "\q"') != 0):
|
||||
print('Invalid user password!')
|
||||
base.print_info('Changing password...')
|
||||
print('Invalid user password, changing...')
|
||||
result = change_userPass(dbUser, dbPass, postgre_path_to_bin) and result
|
||||
else:
|
||||
print('User ' + dbUser + ' not exist!')
|
||||
base.print_info('Creating ' + dbName + ' user...')
|
||||
print('Creating user ' + dbUser + '...')
|
||||
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):
|
||||
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)
|
||||
# Check if database exists
|
||||
db_check_result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + ' -c "SELECT datname FROM pg_database;"')
|
||||
|
||||
if (db_check_result['stdout'].find(dbName) == -1):
|
||||
print('Creating database ' + dbName + '...')
|
||||
create_result = create_postgreDb(dbName, postgre_path_to_bin)
|
||||
|
||||
if create_result:
|
||||
# Grant privileges to user on database and schema
|
||||
base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "GRANT ALL privileges ON DATABASE ' + dbName + ' TO ' + dbUser + ';"')
|
||||
base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-d ' + dbName + ' -c "GRANT ALL ON SCHEMA public TO ' + dbUser + ';"')
|
||||
|
||||
configure_result = configureDb(dbUser, dbName, creatdb_path, postgre_path_to_bin)
|
||||
result = create_result and configure_result
|
||||
else:
|
||||
result = False
|
||||
else:
|
||||
if (base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "SELECT pg_size_pretty(pg_database_size(' + "'" + dbName + "'" + '));"')['stdout'].find('7559 kB') != -1):
|
||||
print('Database ' + dbName + ' not configured')
|
||||
base.print_info('Configuring ' + dbName + ' database...')
|
||||
result = configureDb(dbName, creatdb_path, postgre_path_to_bin) and result
|
||||
print('Database ' + dbName + ' is valid')
|
||||
|
||||
if (base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "\l+ ' + dbName + '"')['stdout'].find(dbUser +'=CTc/' + rootUser) == -1):
|
||||
print('User ' + dbUser + ' has no database privileges!')
|
||||
base.print_info('Setting database privileges for user ' + dbUser + '...')
|
||||
result = set_dbPrivilegesForUser(dbUser, dbName, postgre_path_to_bin) and result
|
||||
print('User ' + dbUser + ' has database privileges')
|
||||
|
||||
# Database exists - check if tables need to be created
|
||||
table_count_result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "SELECT count(*) FROM information_schema.tables WHERE table_schema = \'public\';"')
|
||||
|
||||
needs_configure = False
|
||||
|
||||
if table_count_result['stdout'].find(' 0') != -1:
|
||||
# No tables - need to configure
|
||||
needs_configure = True
|
||||
|
||||
if needs_configure:
|
||||
# Grant privileges and configure
|
||||
base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "GRANT ALL privileges ON DATABASE ' + dbName + ' TO ' + dbUser + ';"')
|
||||
base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-d ' + dbName + ' -c "GRANT ALL ON SCHEMA public TO ' + dbUser + ';"')
|
||||
|
||||
configure_result = configureDb(dbUser, dbName, creatdb_path, postgre_path_to_bin)
|
||||
result = configure_result and result
|
||||
|
||||
return result
|
||||
def create_postgreDb(dbName, postgre_path_to_bin = ''):
|
||||
postgreLoginUser = get_postgreLoginSrting(install_params['PostgreSQL']['root'])
|
||||
if (base.exec_command_in_dir(postgre_path_to_bin, postgreLoginUser + '-c "CREATE DATABASE ' + dbName +';"') != 0):
|
||||
result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginUser + '-c "CREATE DATABASE ' + dbName +';"')
|
||||
if (result['returncode'] != 0):
|
||||
print('Database creation failed!')
|
||||
return False
|
||||
return True
|
||||
def set_dbPrivilegesForUser(userName, dbName, postgre_path_to_bin = ''):
|
||||
postgreLoginUser = get_postgreLoginSrting(install_params['PostgreSQL']['root'])
|
||||
if (base.exec_command_in_dir(postgre_path_to_bin, postgreLoginUser + '-c "GRANT ALL privileges ON DATABASE ' + dbName + ' TO ' + userName + ';"') != 0):
|
||||
result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginUser + '-c "GRANT ALL privileges ON DATABASE ' + dbName + ' TO ' + userName + ';"')
|
||||
if (result['returncode'] != 0):
|
||||
print('Grant privileges failed!')
|
||||
return False
|
||||
return True
|
||||
def create_postgreUser(userName, userPass, postgre_path_to_bin = ''):
|
||||
postgreLoginRoot = get_postgreLoginSrting(install_params['PostgreSQL']['root'])
|
||||
if (base.exec_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "CREATE USER ' + userName + ' WITH password ' + "'" + userPass + "'" + ';"') != 0):
|
||||
result = base.run_command_in_dir(postgre_path_to_bin, postgreLoginRoot + '-c "CREATE USER ' + userName + ' WITH password ' + "'" + userPass + "'" + ';"')
|
||||
if (result['returncode'] != 0):
|
||||
print('User creation failed!')
|
||||
return False
|
||||
return True
|
||||
def change_userPass(userName, userPass, postgre_path_to_bin = ''):
|
||||
@ -766,13 +812,24 @@ def change_userPass(userName, userPass, postgre_path_to_bin = ''):
|
||||
return False
|
||||
return True
|
||||
def configureDb(userName, dbName, scriptPath, postgre_path_to_bin = ''):
|
||||
print('Execution ' + scriptPath)
|
||||
postgreLoginSrt = get_postgreLoginSrting(userName)
|
||||
|
||||
code = base.exec_command_in_dir(postgre_path_to_bin, postgreLoginSrt + ' -d ' + dbName + ' -f "' + scriptPath + '"')
|
||||
if (code != 0):
|
||||
print('Execution failed!')
|
||||
print('Executing ' + scriptPath)
|
||||
|
||||
if not base.is_file(scriptPath):
|
||||
print('ERROR: Script file does not exist!')
|
||||
return False
|
||||
|
||||
postgreLoginSrt = get_postgreLoginSrting(userName)
|
||||
full_command = postgreLoginSrt + ' -d ' + dbName + ' -f "' + scriptPath + '"'
|
||||
|
||||
# Use run_command_in_dir to capture output
|
||||
result = base.run_command_in_dir(postgre_path_to_bin, full_command)
|
||||
|
||||
if (result['returncode'] != 0):
|
||||
print('Execution failed!')
|
||||
if result['stderr']:
|
||||
print('Error: ' + result['stderr'])
|
||||
return False
|
||||
|
||||
print('Execution completed')
|
||||
return True
|
||||
def uninstall_postgresql():
|
||||
|
||||
@ -131,6 +131,8 @@ def make_tar():
|
||||
make_args = ["tar"]
|
||||
if common.platform == "darwin_arm64":
|
||||
make_args += ["-e", "UNAME_M=arm64"]
|
||||
if common.platform == "darwin_x86_64":
|
||||
make_args += ["-e", "UNAME_M=x86_64"]
|
||||
if common.platform == "linux_aarch64":
|
||||
make_args += ["-e", "UNAME_M=aarch64"]
|
||||
if not branding.onlyoffice:
|
||||
@ -168,7 +170,7 @@ def make_wheel():
|
||||
|
||||
utils.delete_dir("python")
|
||||
utils.copy_dir("../onlyoffice/build_tools/packaging/docbuilder/resources", "python")
|
||||
utils.copy_dir(builder_dir, "python/docbuilder/lib")
|
||||
utils.copy_dir(builder_dir, "python/docbuilder/lib", True, True)
|
||||
|
||||
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):
|
||||
@ -202,7 +204,11 @@ def make_wheel():
|
||||
utils.delete_file("docbuilder.net.dll")
|
||||
utils.delete_file("docbuilder.jni.dll")
|
||||
elif utils.is_macos():
|
||||
utils.delete_file("libdocbuilder.jni.dylib")
|
||||
if (utils.is_file("libdocbuilder.jni.dylib")):
|
||||
utils.delete_file("libdocbuilder.jni.dylib")
|
||||
if (utils.is_dir("docbuilder.jni.framework")):
|
||||
utils.delete_file("docbuilder.jni.framework")
|
||||
utils.remove_all_symlinks(".")
|
||||
elif utils.is_linux():
|
||||
utils.delete_file("libdocbuilder.jni.so")
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ def s3_upload(files, dst):
|
||||
|
||||
def make_windows():
|
||||
global package_name, package_version, arch, xp
|
||||
utils.set_cwd("desktop-apps\\win-linux\\package\\windows")
|
||||
utils.set_cwd("desktop-apps\\package")
|
||||
|
||||
package_name = branding.desktop_package_name
|
||||
package_version = common.version + "." + common.build
|
||||
@ -51,34 +51,31 @@ def make_windows():
|
||||
|
||||
if common.clean:
|
||||
utils.log_h2("desktop clean")
|
||||
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_dir("build")
|
||||
utils.delete_files("inno\\package.config")
|
||||
utils.delete_files("inno\\*.exe")
|
||||
utils.delete_dir("advinst\\DesktopEditors-cache")
|
||||
utils.delete_files("advinst\\package.config")
|
||||
utils.delete_files("advinst\\*.msi")
|
||||
utils.delete_files("advinst\\*.aic")
|
||||
utils.delete_dir("zip")
|
||||
|
||||
if not xp:
|
||||
make_prepare()
|
||||
make_zip()
|
||||
make_inno()
|
||||
if branding.onlyoffice:
|
||||
make_inno()
|
||||
make_inno("standalone")
|
||||
make_inno("update")
|
||||
make_advinst()
|
||||
make_advinst()
|
||||
|
||||
make_prepare("commercial")
|
||||
make_zip("commercial")
|
||||
make_inno("commercial")
|
||||
make_advinst("commercial")
|
||||
make_prepare("commercial")
|
||||
make_zip("commercial")
|
||||
make_inno("commercial")
|
||||
make_advinst("commercial")
|
||||
else:
|
||||
make_prepare("xp")
|
||||
make_zip("xp")
|
||||
make_inno("xp")
|
||||
# Disable build online installer
|
||||
# if common.platform == "windows_x86_xp":
|
||||
# make_online()
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
return
|
||||
@ -87,7 +84,8 @@ def make_prepare(edition = "opensource"):
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch,
|
||||
"-Target", edition
|
||||
"-Target", edition,
|
||||
"-CompanyName", branding.company_name
|
||||
]
|
||||
if common.sign:
|
||||
args += ["-Sign"]
|
||||
@ -101,11 +99,12 @@ def make_zip(edition = "opensource"):
|
||||
if edition == "commercial": zip_file = "%s-Enterprise-%s-%s.zip"
|
||||
elif edition == "xp": zip_file = "%s-XP-%s-%s.zip"
|
||||
else: zip_file = "%s-%s-%s.zip"
|
||||
zip_file = zip_file % (package_name, package_version, arch)
|
||||
zip_file = "zip\\" + zip_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch,
|
||||
"-Target", edition
|
||||
"-Target", edition,
|
||||
"-CompanyName", branding.company_name
|
||||
]
|
||||
# if common.sign:
|
||||
# args += ["-Sign"]
|
||||
@ -126,7 +125,7 @@ def make_inno(edition = "opensource"):
|
||||
elif edition == "update": inno_file = "%s-Update-%s-%s.exe"
|
||||
elif edition == "xp": inno_file = "%s-XP-%s-%s.exe"
|
||||
else: inno_file = "%s-%s-%s.exe"
|
||||
inno_file = inno_file % (package_name, package_version, arch)
|
||||
inno_file = "inno\\" + inno_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch,
|
||||
@ -151,7 +150,7 @@ def make_inno(edition = "opensource"):
|
||||
def make_advinst(edition = "opensource"):
|
||||
if edition == "commercial": advinst_file = "%s-Enterprise-%s-%s.msi"
|
||||
else: advinst_file = "%s-%s-%s.msi"
|
||||
advinst_file = advinst_file % (package_name, package_version, arch)
|
||||
advinst_file = "advinst\\" + advinst_file % (package_name, package_version, arch)
|
||||
args = [
|
||||
"-Version", package_version,
|
||||
"-Arch", arch,
|
||||
@ -170,18 +169,6 @@ def make_advinst(edition = "opensource"):
|
||||
utils.set_summary("desktop advinst " + edition + " deploy", ret)
|
||||
return
|
||||
|
||||
def make_online():
|
||||
online_file = utils.glob_file("OnlineInstaller-" + package_version + "*.exe")
|
||||
utils.log_h2("desktop online installer build")
|
||||
ret = utils.is_file(online_file)
|
||||
utils.set_summary("desktop online installer build", ret)
|
||||
|
||||
if common.deploy and ret:
|
||||
utils.log_h2("desktop online installer deploy")
|
||||
ret = s3_upload([online_file], "desktop/win/online/")
|
||||
utils.set_summary("desktop online installer deploy", ret)
|
||||
return
|
||||
|
||||
#
|
||||
# macOS
|
||||
#
|
||||
@ -328,7 +315,7 @@ def make_sparkle_updates():
|
||||
#
|
||||
|
||||
def make_linux():
|
||||
utils.set_cwd("desktop-apps/win-linux/package/linux")
|
||||
utils.set_cwd("desktop-apps/package")
|
||||
|
||||
for edition in ["opensource", "commercial"]:
|
||||
utils.log_h2("desktop " + edition + " build")
|
||||
@ -338,14 +325,19 @@ def make_linux():
|
||||
if common.platform == "linux_aarch64":
|
||||
make_args += ["-e", "UNAME_M=aarch64"]
|
||||
if not branding.onlyoffice:
|
||||
make_args += ["-e", "BRANDING_DIR=../../../../" + common.branding + "/desktop-apps/win-linux/package/linux"]
|
||||
make_args += ["-e", "BRANDING_DIR=../../" + common.branding + "/desktop-apps/package"]
|
||||
ret = utils.sh("make clean && make " + " ".join(make_args), verbose=True)
|
||||
utils.set_summary("desktop " + edition + " build", ret)
|
||||
|
||||
if common.deploy:
|
||||
for t in branding.desktop_make_targets:
|
||||
utils.log_h2("desktop " + edition + " " + t["make"] + " deploy")
|
||||
ret = s3_upload(utils.glob_path(t["src"]), t["dst"])
|
||||
uploads = []
|
||||
for f in utils.glob_path(t["src"]):
|
||||
if "help" in f and not \
|
||||
("x86_64" in common.platform and edition == "opensource"): continue
|
||||
uploads.append(f)
|
||||
ret = s3_upload(uploads, t["dst"])
|
||||
utils.set_summary("desktop " + edition + " " + t["make"] + " deploy", ret)
|
||||
|
||||
utils.set_cwd(common.workspace_dir)
|
||||
|
||||
@ -201,12 +201,12 @@ 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, verbose=True, symlinks=False):
|
||||
if verbose:
|
||||
log("- copy_dir:")
|
||||
log(" src: " + src)
|
||||
log(" dst: " + dst)
|
||||
shutil.copytree(src, dst)
|
||||
shutil.copytree(src, dst, symlinks=symlinks)
|
||||
return
|
||||
|
||||
def copy_dir_content(src, dst, filter_include = "", filter_exclude = "", verbose=True):
|
||||
@ -262,6 +262,20 @@ def delete_files(src, verbose=True):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
return
|
||||
|
||||
def remove_all_symlinks(dir):
|
||||
for root, dirs, files in os.walk(dir, topdown=True, followlinks=False):
|
||||
for name in files:
|
||||
path = os.path.join(root, name)
|
||||
if os.path.islink(path):
|
||||
os.unlink(path)
|
||||
|
||||
for name in list(dirs):
|
||||
path = os.path.join(root, name)
|
||||
if os.path.islink(path):
|
||||
os.unlink(path)
|
||||
dirs.remove(name)
|
||||
return
|
||||
|
||||
def set_summary(target, status):
|
||||
common.summary.append({target: status})
|
||||
return
|
||||
|
||||
@ -36,7 +36,7 @@ def make(platform, project, qmake_config_addon="", is_no_errors=False):
|
||||
return
|
||||
|
||||
old_env = dict(os.environ)
|
||||
|
||||
|
||||
# qt
|
||||
qt_dir = base.qt_setup(platform)
|
||||
base.set_env("OS_DEPLOY", platform)
|
||||
@ -50,7 +50,7 @@ def make(platform, project, qmake_config_addon="", is_no_errors=False):
|
||||
if (pro_dir.endswith("/")):
|
||||
pro_dir = pro_dir[:-1]
|
||||
|
||||
makefile_name = "Makefile." + get_make_file_suffix(platform)
|
||||
makefile_name = "Makefile." + get_make_file_suffix(platform)
|
||||
makefile = pro_dir + "/" + makefile_name
|
||||
stash_file = pro_dir + "/.qmake.stash"
|
||||
|
||||
@ -73,6 +73,11 @@ def make(platform, project, qmake_config_addon="", is_no_errors=False):
|
||||
# setup ios env
|
||||
if (-1 != platform.find("ios")):
|
||||
base.hack_xcode_ios()
|
||||
sdk_name = "iphoneos"
|
||||
if qmake_config_addon.find("ios_simulator") != -1:
|
||||
sdk_name = "iphonesimulator"
|
||||
base.set_env("SDK_PATH", base.find_ios_sdk(sdk_name))
|
||||
base.set_env("XCODE_TOOLCHAIN_PATH", base.find_xcode_toolchain(sdk_name))
|
||||
|
||||
if base.is_file(makefile):
|
||||
base.delete_file(makefile)
|
||||
@ -100,19 +105,35 @@ def make(platform, project, qmake_config_addon="", is_no_errors=False):
|
||||
if "1" == config.option("use-clang"):
|
||||
build_params.append("-spec")
|
||||
build_params.append("linux-clang-libc++")
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
base.set_sysroot_env()
|
||||
base.cmd_exe(qmake_app, build_params) # calls cmd_exe to pass os.env
|
||||
else:
|
||||
base.cmd(qmake_app, build_params)
|
||||
sysroot_path = config.option("sysroot_" + platform)
|
||||
os.environ['QMAKE_CUSTOM_SYSROOT'] = sysroot_path
|
||||
os.environ['QMAKE_CUSTOM_SYSROOT_BIN'] = config.get_custom_sysroot_bin(platform)
|
||||
os.environ['PKG_CONFIG_PATH'] = config.get_custom_sysroot_lib(platform, True) + "/pkgconfig"
|
||||
os.environ['PKG_CONFIG_SYSROOT_DIR'] = sysroot_path
|
||||
|
||||
base.cmd_exe(qmake_app, build_params)
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
base.set_sysroot_env(platform)
|
||||
|
||||
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)
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
base.restore_sysroot_env()
|
||||
base.cmd(qmake_app, build_params)
|
||||
if "" != config.option("sysroot"):
|
||||
base.set_sysroot_env(platform)
|
||||
|
||||
base.correct_makefile_after_qmake(platform, makefile)
|
||||
base.cmd_and_return_cwd("make", ["-f", makefile] + get_j_num(), is_no_errors)
|
||||
|
||||
if "" != config.option("sysroot"):
|
||||
base.restore_sysroot_env()
|
||||
else:
|
||||
config_params_array = base.qt_config_as_param(config_param)
|
||||
config_params_string = ""
|
||||
|
||||
@ -14,7 +14,7 @@ and Plugins (Methods/Events) API using the following Python scripts:
|
||||
|
||||
```bash
|
||||
Node.js v20 and above
|
||||
Python v3.10 and above
|
||||
Python v3.12 and above
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
@ -66,11 +66,21 @@ exports.handlers = {
|
||||
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 =
|
||||
let shouldAddMethod =
|
||||
doclet.kind !== 'member' &&
|
||||
(!doclet.longname || doclet.longname.search('private') === -1) &&
|
||||
doclet.scope !== 'inner' && hasTypeofEditorsTag;
|
||||
|
||||
// class names may be the same between editors, we check against the inheritance tree
|
||||
if (doclet.inherits) {
|
||||
const parentClass = doclet.inherits.split('#')[0];
|
||||
const curClass = cleanName(doclet.memberof);
|
||||
|
||||
if (!classesDocletsMap[curClass].augments || !classesDocletsMap[curClass].augments.includes(parentClass)) {
|
||||
shouldAddMethod = false;
|
||||
}
|
||||
}
|
||||
|
||||
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))) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/pdf/apiBuilder.js"]
|
||||
"include": ["../../../../../sdkjs/word/apiBuilder.js", "../../../../../sdkjs/pdf/apiBuilder.js"]
|
||||
},
|
||||
"plugins": ["./correct_doclets.js"],
|
||||
"opts": {
|
||||
@ -13,4 +13,4 @@
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,14 +13,16 @@ configs = [
|
||||
"./config/word.json",
|
||||
"./config/cell.json",
|
||||
"./config/slide.json",
|
||||
"./config/forms.json"
|
||||
"./config/forms.json",
|
||||
"./config/pdf.json"
|
||||
]
|
||||
|
||||
editors_maps = {
|
||||
"word": "CDE",
|
||||
"cell": "CSE",
|
||||
"slide": "CPE",
|
||||
"forms": "CFE"
|
||||
"forms": "CFE",
|
||||
"pdf": "PDFE"
|
||||
}
|
||||
|
||||
def generate(output_dir, md=False):
|
||||
@ -77,10 +79,7 @@ def generate(output_dir, md=False):
|
||||
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```'
|
||||
doclet['description'] = doclet['description'] + f'\n\n## Try it\n\n ```js document-builder={{"documentType": "{editor_name}"}}\n{code_content}\n```'
|
||||
|
||||
# Write the modified JSON file back
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
|
||||
@ -4,13 +4,16 @@ import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_json
|
||||
import json
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
# Configuration files
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
"forms": "form-api",
|
||||
"pdf": "pdf-api",
|
||||
}
|
||||
|
||||
|
||||
@ -19,9 +22,36 @@ root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../.
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
|
||||
translations = {}
|
||||
translations_lang = None
|
||||
missed_translations = {}
|
||||
used_translations_keys = {}
|
||||
global_output_dir = ""
|
||||
cur_editor_name = None
|
||||
|
||||
def find_common_path_part(path_full: str, path_suffix: str, anchor: str) -> str:
|
||||
path_full = path_full.replace('\\', '/')
|
||||
path_suffix = path_suffix.replace('\\', '/')
|
||||
|
||||
parts1 = PurePosixPath(path_full).parts
|
||||
parts2 = PurePosixPath(path_suffix).parts
|
||||
|
||||
try:
|
||||
idx1 = [p.lower() for p in parts1].index(anchor.lower())
|
||||
idx2 = [p.lower() for p in parts2].index(anchor.lower())
|
||||
except ValueError:
|
||||
return ""
|
||||
|
||||
common_segments = []
|
||||
|
||||
for p1, p2 in zip(parts1[idx1:], parts2[idx2:]):
|
||||
if p1.lower() == p2.lower():
|
||||
common_segments.append(p1)
|
||||
else:
|
||||
break
|
||||
|
||||
return "/".join(common_segments)
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
@ -35,6 +65,21 @@ def remove_js_comments(text):
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL) # multi-line
|
||||
return text.strip()
|
||||
|
||||
def get_translation(key):
|
||||
def process_part(k):
|
||||
if k not in translations:
|
||||
missed_translations[k] = k
|
||||
else:
|
||||
used_translations_keys[k] = True
|
||||
return translations.get(k, k)
|
||||
|
||||
if '\\\n' in key:
|
||||
parts = key.split('\\\n')
|
||||
translated_parts = [process_part(p) for p in parts]
|
||||
return '\\\n'.join(translated_parts)
|
||||
|
||||
return process_part(key)
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
Finds patterns like {@link ...} and replaces them with Markdown links.
|
||||
@ -42,27 +87,22 @@ def process_link_tags(text, root=''):
|
||||
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"
|
||||
content = match.group(1).strip() # Example: "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)
|
||||
if ref.startswith('/docs/'):
|
||||
url = root + '../../../..' + ref
|
||||
display_text = label if label else ref
|
||||
|
||||
if url.endswith('/'):
|
||||
last_dir = url.rstrip('/').split('/')[-1]
|
||||
url = f"{url}{last_dir}"
|
||||
|
||||
return f"[{display_text}]({url}.md)"
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
@ -90,7 +130,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
return get_translation('No description provided.')
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
@ -99,6 +139,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
string = remove_line_breaks(string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
@ -108,7 +149,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
return get_translation(string)
|
||||
|
||||
def correct_default_value(value, enumerations, classes):
|
||||
if value is None or value == '':
|
||||
@ -305,12 +346,12 @@ def generate_data_types_markdown(types, enumerations, classes, root='../../'):
|
||||
|
||||
|
||||
def generate_class_markdown(class_name, methods, properties, enumerations, classes):
|
||||
content = f"# {class_name}\n\nRepresents the {class_name} class.\n\n"
|
||||
content = f"# {class_name}\n\n{get_translation(f"Represents the {class_name} class.")}\n\n"
|
||||
|
||||
content += generate_properties_markdown(properties, enumerations, classes)
|
||||
|
||||
content += "\n## Methods\n\n"
|
||||
content += "| Method | Returns | Description |\n"
|
||||
content += f"\n## {get_translation(f"Methods")}\n\n"
|
||||
content += f"| {get_translation(f"Method")} | {get_translation(f"Returns")} | {get_translation(f"Description")} |\n"
|
||||
content += "| ------ | ------- | ----------- |\n"
|
||||
|
||||
for method in sorted(methods, key=lambda m: m['name']):
|
||||
@ -322,10 +363,10 @@ def generate_class_markdown(class_name, methods, properties, enumerations, class
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
returns_markdown = generate_data_types_markdown(return_type_list, enumerations, classes, '../')
|
||||
else:
|
||||
returns_markdown = "None"
|
||||
returns_markdown = get_translation(f"None")
|
||||
|
||||
# Processing the method description
|
||||
description = remove_line_breaks(correct_description(method.get('description', 'No description provided.'), '../', True))
|
||||
description = 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)"
|
||||
@ -347,47 +388,47 @@ def generate_method_markdown(method, enumerations, classes, example_editor_name)
|
||||
|
||||
# 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"
|
||||
content += f"## {get_translation(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"
|
||||
content += f"`expression` - {get_translation(f"A variable that represents a [{memberof}](../{memberof}.md) class.")}\n\n"
|
||||
|
||||
# Parameters
|
||||
content += "## Parameters\n\n"
|
||||
content += f"## {get_translation(f"Parameters")}\n\n"
|
||||
if params:
|
||||
content += "| **Name** | **Required/Optional** | **Data type** | **Default** | **Description** |\n"
|
||||
content += f"| **{get_translation(f"Name")}** | **{get_translation(f"Required/Optional")}** | **{get_translation(f"Data type")}** | **{get_translation(f"Default")}** | **{get_translation(f"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_desc = correct_description(param.get('description', 'No description provided.'), '../../', True)
|
||||
param_required = f"{get_translation(f"Required")}" if not param.get('optional') else f"{get_translation(f"Optional")}"
|
||||
param_default = correct_default_value(param.get('defaultvalue', ''), enumerations, classes)
|
||||
|
||||
content += f"| {param_name} | {param_required} | {param_types_md} | {param_default} | {param_desc} |\n"
|
||||
else:
|
||||
content += "This method doesn't have any parameters.\n"
|
||||
content += f"{get_translation("This method doesn't have any parameters.")}\n"
|
||||
|
||||
# Returns
|
||||
content += "\n## Returns\n\n"
|
||||
content += f"\n## {get_translation(f"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."
|
||||
content += get_translation(f"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"
|
||||
comment = get_translation(comment.strip())
|
||||
content += f"\n\n## {get_translation(f"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"
|
||||
content += f"\n\n## {get_translation(f"Example")}\n\n```javascript {example_editor_name}\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
@ -395,14 +436,14 @@ def generate_properties_markdown(properties, enumerations, classes, root='../'):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content = f"## {get_translation(f"Properties")}\n\n"
|
||||
content += f"| {get_translation(f"Name")} | {get_translation(f"Type")} | {get_translation(f"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_description = 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"
|
||||
@ -426,8 +467,8 @@ def generate_enumeration_markdown(enumeration, enumerations, classes, example_ed
|
||||
if ptype['type'] == 'TypeUnion':
|
||||
enum_empty = True # is empty enum
|
||||
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
content += f"## {get_translation(f"Type")}\n\n{get_translation(f"Enumeration")}\n\n"
|
||||
content += f"## {get_translation(f"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)
|
||||
@ -447,25 +488,25 @@ def generate_enumeration_markdown(enumeration, enumerations, classes, example_ed
|
||||
if enum_empty == True:
|
||||
return None
|
||||
elif enumeration['properties'] is not None:
|
||||
content += "## Type\n\nObject\n\n"
|
||||
content += f"## {get_translation(f"Type")}\n\n{get_translation(f"Object")}\n\n"
|
||||
content += generate_properties_markdown(enumeration['properties'], enumerations, classes)
|
||||
else:
|
||||
content += "## Type\n\n"
|
||||
content += f"## {get_translation(f"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)
|
||||
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"
|
||||
comment = get_translation(comment.strip())
|
||||
content += f"\n\n## {get_translation(f"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"
|
||||
content += f"\n\n## {get_translation(f"Example")}\n\n```javascript {example_editor_name}\n{cleaned_example}\n```\n"
|
||||
|
||||
return escape_text_outside_code_blocks(content)
|
||||
|
||||
@ -482,11 +523,13 @@ def process_doclets(data, output_dir, editor_name):
|
||||
if editor_name == 'word':
|
||||
example_editor_name += 'docx'
|
||||
elif editor_name == 'forms':
|
||||
example_editor_name += 'pdf'
|
||||
example_editor_name += 'forms'
|
||||
elif editor_name == 'slide':
|
||||
example_editor_name += 'pptx'
|
||||
elif editor_name == 'cell':
|
||||
example_editor_name += 'xlsx'
|
||||
elif editor_name == 'pdf':
|
||||
example_editor_name += 'pdf'
|
||||
|
||||
for doclet in data:
|
||||
if doclet['kind'] == 'class':
|
||||
@ -553,7 +596,18 @@ def process_doclets(data, output_dir, editor_name):
|
||||
if not enum.get('example', ''):
|
||||
missing_examples.append(os.path.relpath(enum_file_path, output_dir))
|
||||
|
||||
def generate(output_dir):
|
||||
def generate(output_dir, translations_file):
|
||||
global translations
|
||||
global translations_lang
|
||||
global global_output_dir
|
||||
global_output_dir = output_dir
|
||||
|
||||
if translations_file is not None and os.path.exists(translations_file):
|
||||
translations = load_json(translations_file)
|
||||
translations_lang = os.path.splitext(os.path.basename(translations_file))[0]
|
||||
else:
|
||||
translations = {}
|
||||
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
print('Generating Markdown documentation...')
|
||||
@ -572,6 +626,21 @@ def generate(output_dir):
|
||||
used_enumerations.clear()
|
||||
process_doclets(data, output_dir, editor_name)
|
||||
|
||||
if translations_file is not None:
|
||||
target_dir = os.path.dirname(translations_file)
|
||||
|
||||
missed_file_path = os.path.join(target_dir, "missed_translations.json")
|
||||
print(f'Saving missed translations to: {missed_file_path}')
|
||||
with open(missed_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(missed_translations, f, ensure_ascii=False, indent=4)
|
||||
|
||||
unused_keys = set(translations.keys()) - set(used_translations_keys.keys())
|
||||
unused_data = {k: translations[k] for k in unused_keys}
|
||||
unused_file_path = os.path.join(target_dir, "unused_translations.json")
|
||||
print(f'Saving unused translations to: {unused_file_path}')
|
||||
with open(unused_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(unused_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
shutil.rmtree(output_dir + 'tmp_json')
|
||||
print('Done')
|
||||
|
||||
@ -584,8 +653,17 @@ if __name__ == "__main__":
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/office-api/usage-api/" # Default value
|
||||
)
|
||||
parser.add_argument(
|
||||
"--translations",
|
||||
type=str,
|
||||
help="Path to the JSON file with translations",
|
||||
nargs='?',
|
||||
default=None
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
|
||||
generate(args.destination, args.translations)
|
||||
print("START_MISSING_EXAMPLES")
|
||||
print(",".join(missing_examples))
|
||||
print("END_MISSING_EXAMPLES")
|
||||
|
||||
@ -11,14 +11,16 @@ editors = [
|
||||
"word",
|
||||
"cell",
|
||||
"slide",
|
||||
"forms"
|
||||
"forms",
|
||||
"pdf"
|
||||
]
|
||||
|
||||
editors_names = {
|
||||
"word": "Word",
|
||||
"cell": "Spreadsheet",
|
||||
"slide": "Presentation",
|
||||
"forms": "Forms"
|
||||
"forms": "Forms",
|
||||
"pdf": "PDF"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/events/pdf.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/events/pdf.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/pdf/plugin-events.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/pdf.json
Normal file
16
scripts/sdkjs_common/jsdoc/plugins/config/methods/pdf.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": {
|
||||
"include": ["../../../../../sdkjs/pdf/api_plugins.js"]
|
||||
},
|
||||
"plugins": ["../correct_doclets.js"],
|
||||
"opts": {
|
||||
"destination": "./out",
|
||||
"recurse": true,
|
||||
"encoding": "utf8"
|
||||
},
|
||||
"templates": {
|
||||
"json": {
|
||||
"pretty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,8 @@ configs = [
|
||||
"./config/events/word.json",
|
||||
"./config/events/cell.json",
|
||||
"./config/events/slide.json",
|
||||
"./config/events/forms.json"
|
||||
"./config/events/forms.json",
|
||||
"./config/events/pdf.json"
|
||||
]
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
|
||||
@ -5,13 +5,16 @@ import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_events_json
|
||||
import json
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
# Папки для каждого editor_name
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
"forms": "form-api",
|
||||
"pdf": "pdf-api"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
@ -19,7 +22,34 @@ root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../.
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
translations = {}
|
||||
translations_lang = None
|
||||
missed_translations = {}
|
||||
used_translations_keys = {}
|
||||
global_output_dir = ""
|
||||
|
||||
def find_common_path_part(path_full: str, path_suffix: str, anchor: str) -> str:
|
||||
path_full = path_full.replace('\\', '/')
|
||||
path_suffix = path_suffix.replace('\\', '/')
|
||||
|
||||
parts1 = PurePosixPath(path_full).parts
|
||||
parts2 = PurePosixPath(path_suffix).parts
|
||||
|
||||
try:
|
||||
idx1 = [p.lower() for p in parts1].index(anchor.lower())
|
||||
idx2 = [p.lower() for p in parts2].index(anchor.lower())
|
||||
except ValueError:
|
||||
return ""
|
||||
|
||||
common_segments = []
|
||||
|
||||
for p1, p2 in zip(parts1[idx1:], parts2[idx2:]):
|
||||
if p1.lower() == p2.lower():
|
||||
common_segments.append(p1)
|
||||
else:
|
||||
break
|
||||
|
||||
return "/".join(common_segments)
|
||||
|
||||
def load_json(path):
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
@ -37,6 +67,20 @@ def remove_js_comments(text):
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
|
||||
return text.strip()
|
||||
|
||||
def get_translation(key):
|
||||
def process_part(k):
|
||||
if k not in translations:
|
||||
missed_translations[k] = k
|
||||
else:
|
||||
used_translations_keys[k] = True
|
||||
return translations.get(k, k)
|
||||
|
||||
if '\\\n' in key:
|
||||
parts = key.split('\\\n')
|
||||
translated_parts = [process_part(p) for p in parts]
|
||||
return '\\\n'.join(translated_parts)
|
||||
|
||||
return process_part(key)
|
||||
|
||||
def correct_description(string, root='', isInTable=False):
|
||||
"""
|
||||
@ -48,7 +92,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
return get_translation('No description provided.')
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
@ -57,6 +101,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
string = remove_line_breaks(string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
@ -66,7 +111,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
return get_translation(string)
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
@ -75,31 +120,22 @@ def process_link_tags(text, root=''):
|
||||
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"
|
||||
content = match.group(1).strip() # Example: "global#ShapeType shape type" or "global#ErrorValue ErrorValue
|
||||
parts = content.split()
|
||||
ref = parts[0]
|
||||
label = parts[1] if len(parts) > 1 else None
|
||||
|
||||
if ref.startswith('/'):
|
||||
# Handle reserved links using mapping
|
||||
if ref in reserved_links:
|
||||
url = reserved_links[ref]
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
elif ref.startswith('/docs/plugins/'):
|
||||
url = f"../../{ref.split('/docs/plugins/')[1]}.md"
|
||||
display_text = label if label else ref
|
||||
return f"[{display_text}]({url})"
|
||||
else:
|
||||
# If the link is not in the mapping, return the original construction
|
||||
return match.group(0)
|
||||
if ref.startswith('/docs/'):
|
||||
url = root + '../../../..' + ref
|
||||
display_text = label if label else ref
|
||||
|
||||
if url.endswith('/'):
|
||||
last_dir = url.rstrip('/').split('/')[-1]
|
||||
url = f"{url}{last_dir}"
|
||||
|
||||
return f"[{display_text}]({url}.md)"
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
@ -160,26 +196,26 @@ def escape_text_outside_code_blocks(md):
|
||||
|
||||
def generate_event_markdown(event, enumerations):
|
||||
name = event['name']
|
||||
desc = correct_description(event.get('description', ''))
|
||||
desc = correct_description(event.get('description', ''), '../', True)
|
||||
params = event.get('params', [])
|
||||
|
||||
md = f"# {name}\n\n{desc}\n\n"
|
||||
|
||||
# Parameters
|
||||
md += "## Parameters\n\n"
|
||||
md += f"## {get_translation("Parameters")}\n\n"
|
||||
if params:
|
||||
md += "| **Name** | **Data type** | **Description** |\n"
|
||||
md += f"| **{get_translation("Name")}** | **{get_translation("Data type")}** | **{get_translation("Description")}** |\n"
|
||||
md += "| --------- | ------------- | ----------- |\n"
|
||||
for p in params:
|
||||
t_md = generate_data_types_markdown(
|
||||
p.get('type', {}).get('names', []),
|
||||
enumerations
|
||||
)
|
||||
d = remove_line_breaks(correct_description(p.get('description', ''), isInTable=True))
|
||||
d = correct_description(p.get('description', ''), isInTable=True)
|
||||
md += f"| {p['name']} | {t_md} | {d} |\n"
|
||||
md += "\n"
|
||||
else:
|
||||
md += "This event has no parameters.\n\n"
|
||||
md += f"{get_translation("This event has no parameters.")}\n\n"
|
||||
|
||||
for ex in event.get('examples', []):
|
||||
code = remove_js_comments(ex).strip()
|
||||
@ -212,7 +248,7 @@ def generate_enumeration_markdown(enumeration, enumerations):
|
||||
# If parsedType is missing, just list 'type.names' if available
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations)
|
||||
content += t_md + "\n\n"
|
||||
else:
|
||||
@ -220,8 +256,8 @@ def generate_enumeration_markdown(enumeration, enumerations):
|
||||
|
||||
# 1) Handle TypeUnion
|
||||
if ptype == 'TypeUnion':
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n{get_translation("Enumeration")}\n\n"
|
||||
content += f"## {get_translation("Values")}\n\n"
|
||||
for raw_t in enumeration['type']['names']:
|
||||
# Attempt linking
|
||||
if any(enum['name'] == raw_t for enum in enumerations):
|
||||
@ -232,11 +268,11 @@ def generate_enumeration_markdown(enumeration, enumerations):
|
||||
|
||||
# 2) Handle TypeApplication (e.g. Object.<string, string>)
|
||||
elif ptype == 'TypeApplication':
|
||||
content += "## Type\n\nObject\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n{get_translation("Object")}\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"
|
||||
content += f"**{get_translation("Type")}:** {t_md}\n\n"
|
||||
|
||||
# 3) If properties are present, treat it like an object
|
||||
if enumeration.get('properties') is not None:
|
||||
@ -246,16 +282,16 @@ def generate_enumeration_markdown(enumeration, enumerations):
|
||||
if ptype not in ('TypeUnion', 'TypeApplication'):
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
content += f"## {get_translation("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"
|
||||
content += f"\n\n## {get_translation("Examples")}\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
content += f"\n\n## {get_translation("Example")}\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
@ -264,15 +300,15 @@ def generate_enumeration_markdown(enumeration, enumerations):
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
comment = get_translation(comment.strip())
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
content += f"**{get_translation("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"
|
||||
content += f"**{get_translation("Example")} {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
@ -283,13 +319,13 @@ def generate_events_summary(events):
|
||||
Create Events.md summary listing all events with their description.
|
||||
"""
|
||||
header = [
|
||||
"# Events\n\n",
|
||||
"| Event | Description |\n",
|
||||
f"# {get_translation("Events")}\n\n",
|
||||
f"| {get_translation("Event")} | {get_translation("Description")} |\n",
|
||||
"| ----- | ----------- |\n"
|
||||
]
|
||||
lines = [
|
||||
f"| [{ev['name']}](./{ev['name']}.md) | "
|
||||
f"{remove_line_breaks(correct_description(ev.get('description', ''), isInTable=True))} |\n"
|
||||
f"{correct_description(ev.get('description', ''), '../', isInTable=True)} |\n"
|
||||
for ev in sorted(events, key=lambda e: e['name'])
|
||||
]
|
||||
return "".join(header + lines)
|
||||
@ -298,14 +334,14 @@ def generate_properties_markdown(properties, enumerations):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content = f"## {get_translation("Properties")}\n\n"
|
||||
content += f"| {get_translation("Name")} | {get_translation("Type")} | {get_translation("Description")} |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
|
||||
for prop in sorted(properties, key=lambda m: m['name']):
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description, isInTable=True))
|
||||
prop_description = correct_description(prop_description, isInTable=True)
|
||||
prop_types = prop['type']['names'] if prop.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(prop_types, enumerations)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
@ -374,7 +410,18 @@ def process_events(data, editor_dir):
|
||||
# events summary
|
||||
write_markdown_file(os.path.join(events_dir, "Events.md"), generate_events_summary(events))
|
||||
|
||||
def generate_events(output_dir):
|
||||
def generate_events(output_dir, translations_file):
|
||||
global translations
|
||||
global translations_lang
|
||||
global global_output_dir
|
||||
global_output_dir = output_dir
|
||||
|
||||
if translations_file is not None and os.path.exists(translations_file):
|
||||
translations = load_json(translations_file)
|
||||
translations_lang = os.path.splitext(os.path.basename(translations_file))[0]
|
||||
else:
|
||||
translations = {}
|
||||
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
if output_dir.endswith('/'):
|
||||
@ -387,6 +434,21 @@ def generate_events(output_dir):
|
||||
data = load_json(os.path.join(tmp, f"{editor_name}.json"))
|
||||
process_events(data, os.path.join(output_dir, folder))
|
||||
|
||||
if translations_file is not None:
|
||||
target_dir = os.path.dirname(translations_file)
|
||||
|
||||
missed_file_path = os.path.join(target_dir, "missed_translations.json")
|
||||
print(f'Saving missed translations to: {missed_file_path}')
|
||||
with open(missed_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(missed_translations, f, ensure_ascii=False, indent=4)
|
||||
|
||||
unused_keys = set(translations.keys()) - set(used_translations_keys.keys())
|
||||
unused_data = {k: translations[k] for k in unused_keys}
|
||||
unused_file_path = os.path.join(target_dir, "unused_translations.json")
|
||||
print(f'Saving unused translations to: {unused_file_path}')
|
||||
with open(unused_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(unused_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
shutil.rmtree(tmp)
|
||||
print("Done. Missing examples:", missing_examples)
|
||||
|
||||
@ -399,5 +461,14 @@ if __name__ == "__main__":
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/plugin-and-macros/interacting-with-editors/",
|
||||
help="Output directory"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--translations",
|
||||
type=str,
|
||||
help="Path to the JSON file with translations",
|
||||
nargs='?',
|
||||
default=None
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
generate_events(args.destination)
|
||||
|
||||
generate_events(args.destination, args.translations)
|
||||
@ -10,7 +10,8 @@ configs = [
|
||||
"./config/methods/word.json",
|
||||
"./config/methods/cell.json",
|
||||
"./config/methods/slide.json",
|
||||
"./config/methods/forms.json"
|
||||
"./config/methods/forms.json",
|
||||
"./config/methods/pdf.json"
|
||||
]
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
|
||||
@ -4,13 +4,16 @@ import re
|
||||
import shutil
|
||||
import argparse
|
||||
import generate_docs_methods_json
|
||||
import json
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
# Configuration files
|
||||
editors = {
|
||||
"word": "text-document-api",
|
||||
"cell": "spreadsheet-api",
|
||||
"slide": "presentation-api",
|
||||
"forms": "form-api"
|
||||
"forms": "form-api",
|
||||
"pdf": "pdf-api"
|
||||
}
|
||||
|
||||
script_path = os.path.abspath(__file__)
|
||||
@ -18,9 +21,36 @@ root = os.path.abspath(os.path.join(os.path.dirname(script_path), '../../../../.
|
||||
|
||||
missing_examples = []
|
||||
used_enumerations = set()
|
||||
|
||||
translations = {}
|
||||
translations_lang = None
|
||||
missed_translations = {}
|
||||
used_translations_keys = {}
|
||||
global_output_dir = ""
|
||||
cur_editor_name = None
|
||||
|
||||
def find_common_path_part(path_full: str, path_suffix: str, anchor: str) -> str:
|
||||
path_full = path_full.replace('\\', '/')
|
||||
path_suffix = path_suffix.replace('\\', '/')
|
||||
|
||||
parts1 = PurePosixPath(path_full).parts
|
||||
parts2 = PurePosixPath(path_suffix).parts
|
||||
|
||||
try:
|
||||
idx1 = [p.lower() for p in parts1].index(anchor.lower())
|
||||
idx2 = [p.lower() for p in parts2].index(anchor.lower())
|
||||
except ValueError:
|
||||
return ""
|
||||
|
||||
common_segments = []
|
||||
|
||||
for p1, p2 in zip(parts1[idx1:], parts2[idx2:]):
|
||||
if p1.lower() == p2.lower():
|
||||
common_segments.append(p1)
|
||||
else:
|
||||
break
|
||||
|
||||
return "/".join(common_segments)
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
@ -34,6 +64,21 @@ def remove_js_comments(text):
|
||||
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL) # multi-line
|
||||
return text.strip()
|
||||
|
||||
def get_translation(key):
|
||||
def process_part(k):
|
||||
if k not in translations:
|
||||
missed_translations[k] = k
|
||||
else:
|
||||
used_translations_keys[k] = True
|
||||
return translations.get(k, k)
|
||||
|
||||
if '\\\n' in key:
|
||||
parts = key.split('\\\n')
|
||||
translated_parts = [process_part(p) for p in parts]
|
||||
return '\\\n'.join(translated_parts)
|
||||
|
||||
return process_part(key)
|
||||
|
||||
def process_link_tags(text, root=''):
|
||||
"""
|
||||
Finds patterns like {@link ...} and replaces them with Markdown links.
|
||||
@ -41,36 +86,28 @@ def process_link_tags(text, root=''):
|
||||
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"
|
||||
content = match.group(1).strip() # Example: "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)
|
||||
if ref.startswith('/docs/'):
|
||||
url = root + '../../../..' + ref
|
||||
display_text = label if label else ref
|
||||
|
||||
if url.endswith('/'):
|
||||
last_dir = url.rstrip('/').split('/')[-1]
|
||||
url = f"{url}{last_dir}"
|
||||
|
||||
return f"[{display_text}]({url}.md)"
|
||||
elif ref.startswith("global#"):
|
||||
# Handle links to typedef (similar logic as before)
|
||||
typedef_name = ref.split("#")[1]
|
||||
used_enumerations.add(typedef_name)
|
||||
display_text = label if label else typedef_name
|
||||
return f"[{display_text}]({root}Enumeration/{typedef_name}.md)"
|
||||
elif ref.startswith("https"):
|
||||
display_text = label if label else ref # Keep the full notation, e.g., "Api#CreateSlide"
|
||||
return f"[{display_text}]({ref})"
|
||||
else:
|
||||
# Handle links to class methods like ClassName#MethodName
|
||||
try:
|
||||
@ -92,7 +129,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
- All '\r' characters are replaced with '\n'.
|
||||
"""
|
||||
if string is None:
|
||||
return 'No description provided.'
|
||||
return get_translation('No description provided.')
|
||||
|
||||
if False == isInTable:
|
||||
# Line breaks
|
||||
@ -101,6 +138,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
string = re.sub(r'<b>', '-**', string)
|
||||
else:
|
||||
string = re.sub(r'<b>', '**', string)
|
||||
string = remove_line_breaks(string)
|
||||
|
||||
string = re.sub(r'</b>', '**', string)
|
||||
|
||||
@ -110,7 +148,7 @@ def correct_description(string, root='', isInTable=False):
|
||||
# Process {@link ...} constructions
|
||||
string = process_link_tags(string, root)
|
||||
|
||||
return string
|
||||
return get_translation(string)
|
||||
|
||||
def correct_default_value(value, enumerations, classes):
|
||||
if value is None or value == '':
|
||||
@ -308,12 +346,12 @@ def generate_data_types_markdown(types, enumerations, classes, root='../'):
|
||||
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 = f"# {class_name}\n\n{get_translation(f"Represents the {class_name} class.")}\n\n"
|
||||
|
||||
content += generate_properties_markdown(properties, enumerations, classes)
|
||||
|
||||
content += "\n## Methods\n\n"
|
||||
content += "| Method | Returns | Description |\n"
|
||||
content += f"\n## {get_translation("Methods")}\n\n"
|
||||
content += f"| {get_translation("Method")} | {get_translation("Returns")} | {get_translation("Description")} |\n"
|
||||
content += "| ------ | ------- | ----------- |\n"
|
||||
|
||||
for method in sorted(methods, key=lambda m: m['name']):
|
||||
@ -325,10 +363,10 @@ def generate_class_markdown(class_name, methods, properties, enumerations, class
|
||||
return_type_list = returns[0].get('type', {}).get('names', [])
|
||||
returns_markdown = generate_data_types_markdown(return_type_list, enumerations, classes, '../')
|
||||
else:
|
||||
returns_markdown = "None"
|
||||
returns_markdown = get_translation("None")
|
||||
|
||||
# Processing the method description
|
||||
description = remove_line_breaks(correct_description(method.get('description', 'No description provided.'), '../', True))
|
||||
description = correct_description(method.get('description', 'No description provided.'), '../', True)
|
||||
|
||||
# Form a link to the method document
|
||||
method_link = f"[{method_name}](./{method_name}.md)"
|
||||
@ -357,42 +395,42 @@ def generate_method_markdown(method, enumerations, classes):
|
||||
|
||||
# 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"
|
||||
content += f"## {get_translation("Syntax")}\n\n```javascript\nexpression.{method_name}({param_list});\n```\n\n"
|
||||
if memberof:
|
||||
content += f"`expression` - A variable that represents a [{memberof}](Methods.md) class.\n\n"
|
||||
content += f"`expression` - {get_translation(f"A variable that represents a [{memberof}](Methods.md) class.")}\n\n"
|
||||
|
||||
# Parameters
|
||||
content += "## Parameters\n\n"
|
||||
content += f"## {get_translation("Parameters")}\n\n"
|
||||
if params:
|
||||
content += "| **Name** | **Required/Optional** | **Data type** | **Default** | **Description** |\n"
|
||||
content += f"| **{get_translation("Name")}** | **{get_translation("Required/Optional")}** | **{get_translation("Data type")}** | **{get_translation("Default")}** | **{get_translation("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_desc = correct_description(param.get('description', 'No description provided.'), '../', True)
|
||||
param_required = get_translation("Required") if not param.get('optional') else get_translation("Optional")
|
||||
param_default = correct_default_value(param.get('defaultvalue', ''), enumerations, classes)
|
||||
|
||||
content += f"| {param_name} | {param_required} | {param_types_md} | {param_default} | {param_desc} |\n"
|
||||
else:
|
||||
content += "This method doesn't have any parameters.\n"
|
||||
content += f"{get_translation("This method doesn't have any parameters.")}\n"
|
||||
|
||||
# Returns
|
||||
content += "\n## Returns\n\n"
|
||||
content += f"\n## {get_translation("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."
|
||||
content += get_translation("This method doesn't return any data.")
|
||||
|
||||
# Process examples array
|
||||
if examples:
|
||||
if len(examples) > 1:
|
||||
content += "\n\n## Examples\n\n"
|
||||
content += f"\n\n## {get_translation("Examples")}\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
content += f"\n\n## {get_translation("Example")}\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
@ -401,15 +439,15 @@ def generate_method_markdown(method, enumerations, classes):
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
comment = get_translation(comment.strip())
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
content += f"**{get_translation("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"
|
||||
content += f"**{get_translation("Example")} {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
@ -419,14 +457,14 @@ def generate_properties_markdown(properties, enumerations, classes, root='../'):
|
||||
if properties is None:
|
||||
return ''
|
||||
|
||||
content = "## Properties\n\n"
|
||||
content += "| Name | Type | Description |\n"
|
||||
content = f"## {get_translation("Properties")}\n\n"
|
||||
content += f"| {get_translation("Name")} | {get_translation("Type")} | {get_translation("Description")} |\n"
|
||||
content += "| ---- | ---- | ----------- |\n"
|
||||
|
||||
for prop in sorted(properties, key=lambda m: m['name']):
|
||||
prop_name = prop['name']
|
||||
prop_description = prop.get('description', 'No description provided.')
|
||||
prop_description = remove_line_breaks(correct_description(prop_description, isInTable=True))
|
||||
prop_description = correct_description(prop_description, root, isInTable=True)
|
||||
prop_types = prop['type']['names'] if prop.get('type') else []
|
||||
param_types_md = generate_data_types_markdown(prop_types, enumerations, classes, root)
|
||||
content += f"| {prop_name} | {param_types_md} | {prop_description} |\n"
|
||||
@ -458,7 +496,7 @@ def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
# If parsedType is missing, just list 'type.names' if available
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += t_md + "\n\n"
|
||||
else:
|
||||
@ -466,8 +504,8 @@ def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
|
||||
# 1) Handle TypeUnion
|
||||
if ptype == 'TypeUnion':
|
||||
content += "## Type\n\nEnumeration\n\n"
|
||||
content += "## Values\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n{get_translation("Enumeration")}\n\n"
|
||||
content += f"## {get_translation("Values")}\n\n"
|
||||
for raw_t in enumeration['type']['names']:
|
||||
# Attempt linking
|
||||
if any(enum['name'] == raw_t for enum in enumerations):
|
||||
@ -480,11 +518,11 @@ def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
|
||||
# 2) Handle TypeApplication (e.g. Object.<string, string>)
|
||||
elif ptype == 'TypeApplication':
|
||||
content += "## Type\n\nObject\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n{get_translation("Object")}\n\n"
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += f"**Type:** {t_md}\n\n"
|
||||
content += f"**{get_translation("Type")}:** {t_md}\n\n"
|
||||
|
||||
# 3) If properties are present, treat it like an object
|
||||
if enumeration.get('properties') is not None:
|
||||
@ -494,16 +532,16 @@ def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
if ptype not in ('TypeUnion', 'TypeApplication'):
|
||||
type_names = enumeration['type'].get('names', [])
|
||||
if type_names:
|
||||
content += "## Type\n\n"
|
||||
content += f"## {get_translation("Type")}\n\n"
|
||||
t_md = generate_data_types_markdown(type_names, enumerations, classes)
|
||||
content += t_md + "\n\n"
|
||||
|
||||
# Process examples array
|
||||
if examples:
|
||||
if len(examples) > 1:
|
||||
content += "\n\n## Examples\n\n"
|
||||
content += f"\n\n## {get_translation("Examples")}\n\n"
|
||||
else:
|
||||
content += "\n\n## Example\n\n"
|
||||
content += f"\n\n## {get_translation("Example")}\n\n"
|
||||
|
||||
for i, ex_line in enumerate(examples, start=1):
|
||||
# Remove JS comments
|
||||
@ -512,15 +550,15 @@ def generate_enumeration_markdown(enumeration, enumerations, classes):
|
||||
# Attempt splitting if the user used ```js
|
||||
if '```js' in cleaned_example:
|
||||
comment, code = cleaned_example.split('```js', 1)
|
||||
comment = comment.strip()
|
||||
comment = get_translation(comment.strip())
|
||||
code = code.strip()
|
||||
if len(examples) > 1:
|
||||
content += f"**Example {i}:**\n\n{comment}\n\n"
|
||||
content += f"**{get_translation("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"
|
||||
content += f"**{get_translation("Example")} {i}:**\n\n{comment}\n\n"
|
||||
# No special fences, just show as code
|
||||
content += f"```javascript\n{cleaned_example}\n```\n"
|
||||
|
||||
@ -616,7 +654,18 @@ def process_doclets(data, output_dir, editor_name):
|
||||
if not enum.get('examples', ''):
|
||||
missing_examples.append(os.path.relpath(enum_file_path, output_dir))
|
||||
|
||||
def generate(output_dir):
|
||||
def generate(output_dir, translations_file):
|
||||
global translations
|
||||
global translations_lang
|
||||
global global_output_dir
|
||||
global_output_dir = output_dir
|
||||
|
||||
if translations_file is not None and os.path.exists(translations_file):
|
||||
translations = load_json(translations_file)
|
||||
translations_lang = os.path.splitext(os.path.basename(translations_file))[0]
|
||||
else:
|
||||
translations = {}
|
||||
|
||||
os.chdir(os.path.dirname(script_path))
|
||||
|
||||
print('Generating Markdown documentation...')
|
||||
@ -632,6 +681,21 @@ def generate(output_dir):
|
||||
used_enumerations.clear()
|
||||
process_doclets(data, output_dir, editor_name)
|
||||
|
||||
if translations_file is not None:
|
||||
target_dir = os.path.dirname(translations_file)
|
||||
|
||||
missed_file_path = os.path.join(target_dir, "missed_translations.json")
|
||||
print(f'Saving missed translations to: {missed_file_path}')
|
||||
with open(missed_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(missed_translations, f, ensure_ascii=False, indent=4)
|
||||
|
||||
unused_keys = set(translations.keys()) - set(used_translations_keys.keys())
|
||||
unused_data = {k: translations[k] for k in unused_keys}
|
||||
unused_file_path = os.path.join(target_dir, "unused_translations.json")
|
||||
print(f'Saving unused translations to: {unused_file_path}')
|
||||
with open(unused_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(unused_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
shutil.rmtree(output_dir + '/tmp_json')
|
||||
print('Done')
|
||||
|
||||
@ -644,8 +708,17 @@ if __name__ == "__main__":
|
||||
nargs='?', # Indicates the argument is optional
|
||||
default=f"{root}/api.onlyoffice.com/site/docs/plugin-and-macros/interacting-with-editors/" # Default value
|
||||
)
|
||||
parser.add_argument(
|
||||
"--translations",
|
||||
type=str,
|
||||
help="Path to the JSON file with translations",
|
||||
nargs='?',
|
||||
default=None
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
generate(args.destination)
|
||||
|
||||
generate(args.destination, args.translations)
|
||||
print("START_MISSING_EXAMPLES")
|
||||
print(",".join(missing_examples))
|
||||
print("END_MISSING_EXAMPLES")
|
||||
|
||||
16
sln.json
16
sln.json
@ -13,9 +13,11 @@
|
||||
"core/UnicodeConverter/UnicodeConverter.pro",
|
||||
"core/Common/kernel.pro",
|
||||
"core/Common/Network/network.pro",
|
||||
|
||||
|
||||
"core/OdfFile/Reader/Converter/StarMath2OOXML/StarMath2OOXML.pro",
|
||||
|
||||
"core/DesktopEditor/graphics/pro/graphics.pro",
|
||||
|
||||
|
||||
"core/PdfFile/PdfFile.pro",
|
||||
"core/DjVuFile/DjVuFile.pro",
|
||||
"core/XpsFile/XpsFile.pro",
|
||||
@ -27,10 +29,12 @@
|
||||
|
||||
"core/Apple/IWork.pro",
|
||||
|
||||
"core/DocxRenderer/DocxRenderer.pro",
|
||||
"core/DocxRenderer/DocxRenderer.pro",
|
||||
|
||||
"core/DesktopEditor/doctrenderer/doctrenderer.pro",
|
||||
|
||||
"core/DesktopEditor/xmlsec/src/ooxmlsignature.pro",
|
||||
|
||||
"[!no_x2t]core/OOXML/Projects/Linux/DocxFormatLib/DocxFormatLib.pro",
|
||||
"[!no_x2t]core/OOXML/Projects/Linux/PPTXFormatLib/PPTXFormatLib.pro",
|
||||
"[!no_x2t]core/OOXML/Projects/Linux/XlsbFormatLib/XlsbFormatLib.pro",
|
||||
@ -79,19 +83,17 @@
|
||||
"multimedia" : [
|
||||
"[win,linux]desktop-sdk/ChromiumBasedEditors/videoplayerlib/videoplayerlib.pro"
|
||||
],
|
||||
|
||||
|
||||
"desktop" : [
|
||||
"core",
|
||||
"multimedia",
|
||||
|
||||
"core/DesktopEditor/xmlsec/src/ooxmlsignature.pro",
|
||||
|
||||
"desktop-sdk/ChromiumBasedEditors/lib/ascdocumentscore.pro",
|
||||
"desktop-sdk/ChromiumBasedEditors/lib/ascdocumentscore_helper.pro",
|
||||
|
||||
"[win,linux]desktop-sdk/ChromiumBasedEditors/lib/qt_wrapper/qtascdocumentscore.pro",
|
||||
"[win,linux]desktop-apps/win-linux/ASCDocumentEditor.pro",
|
||||
|
||||
|
||||
"[win]desktop-apps/win-linux/extras/projicons/ProjIcons.pro",
|
||||
"[win,!win_xp]desktop-apps/win-linux/extras/update-daemon/UpdateDaemon.pro"
|
||||
],
|
||||
|
||||
54
tools/common/thumbnails_auto.py
Normal file
54
tools/common/thumbnails_auto.py
Normal file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
import glob
|
||||
from pathlib import Path
|
||||
|
||||
params = sys.argv[1:]
|
||||
|
||||
if (3 != len(params)):
|
||||
print("use: thumbnails_auto.py path_to_builder_directory path_to_input_files_directory path_to_output_files_directory")
|
||||
exit(0)
|
||||
|
||||
base.configure_common_apps()
|
||||
|
||||
directory_x2t = params[0].replace("\\", "/")
|
||||
directory_input = params[1].replace("\\", "/")
|
||||
directory_output = params[2].replace("\\", "/")
|
||||
|
||||
|
||||
if not os.path.exists(directory_output):
|
||||
os.mkdir(directory_output)
|
||||
|
||||
def rename_dir(input, output):
|
||||
if base.is_dir(u"" + directory_output + u"/" + output):
|
||||
base.delete_dir(u"" + directory_output + u"/" + output)
|
||||
os.rename(u"" + directory_output + u"/" + input, u"" + directory_output + u"/" + output)
|
||||
return
|
||||
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "512", "724"])
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "1024", "1448"])
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "324", "458"])
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "648", "916"])
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "256", "368"])
|
||||
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "400", "566"])
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, directory_input, directory_output, "184", "260"])
|
||||
#base.cmd("python", ["thumbnails.py", directory_x2t, directory_input, directory_output, "792", "1098"])
|
||||
|
||||
#rename_dir("[512x724]", "inside_1x_[512x724]")
|
||||
#rename_dir("[1024x1448]", "inside_2x_[1024x1448]")
|
||||
#rename_dir("[228x316]", "main_1x_[228x316]")
|
||||
#rename_dir("[456x632]", "main_2x_[456x632]")
|
||||
#rename_dir("[256x368]", "mobile_[256x368]")
|
||||
#rename_dir("[792x1098]", "source_[792x1098]")
|
||||
|
||||
dirnames = list(Path(directory_output).iterdir())
|
||||
for dir_name in dirnames:
|
||||
if len(list(Path(dir_name).iterdir())) == 0:
|
||||
print("Delete dir ", dir_name)
|
||||
Path(dir_name).rmdir()
|
||||
#base.delete_dir(dir_name)
|
||||
274
tools/common/thumbnails_old.py
Normal file
274
tools/common/thumbnails_old.py
Normal file
@ -0,0 +1,274 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
import glob
|
||||
import imagesize
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from os.path import dirname, abspath, join
|
||||
|
||||
# Python 3 compatibility hack
|
||||
try:
|
||||
unicode('')
|
||||
except NameError:
|
||||
unicode = str
|
||||
|
||||
|
||||
params = sys.argv[1:]
|
||||
|
||||
if (5 != len(params)):
|
||||
print("use: thumbnails.py path_to_builder_directory path_to_input_files_directory path_to_output_files_directory width height")
|
||||
exit(0)
|
||||
|
||||
mapping = {"[512x724]": "inside_1x_[512x724]",
|
||||
"[1024x1448]": "inside_2x_[1024x1448]",
|
||||
"[228x316]": "main_1x_[228x316]",
|
||||
"[456x632]": "main_2x_[456x632]",
|
||||
"[256x368]": "mobile_[256x368]",
|
||||
"[792x1098]": "source_[792x1098]",
|
||||
"[324x458]": "main_1x_[324x458]",
|
||||
"[648x916]": "main_2x_[648x916]",
|
||||
"[400x566]": "pop_up_[400x566]",
|
||||
"[184x260]": "desktop[184x260]",
|
||||
}
|
||||
|
||||
cur_path = os.getcwd()
|
||||
base.configure_common_apps()
|
||||
|
||||
directory_x2t = params[0].replace("\\", "/")
|
||||
directory_input = params[1].replace("\\", "/")
|
||||
directory_output = params[2].replace("\\", "/")
|
||||
th_width = params[3]
|
||||
th_height = params[4]
|
||||
|
||||
docbuilder_path = os.path.join(directory_x2t, "docbuilder.py")
|
||||
if not os.path.isfile(docbuilder_path):
|
||||
print(f"ERROR: docbuilder.py not found in '{directory_x2t}'")
|
||||
exit(1)
|
||||
|
||||
spec = importlib.util.spec_from_file_location("docbuilder", docbuilder_path)
|
||||
docbuilder_mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(docbuilder_mod)
|
||||
|
||||
CDocBuilder = docbuilder_mod.CDocBuilder
|
||||
CDocBuilderValue = docbuilder_mod.CDocBuilderValue
|
||||
|
||||
#output_dir = directory_output + "/[" + str(th_width) + "x" + str(th_height) + "]"
|
||||
#if base.is_dir(output_dir):
|
||||
# base.delete_dir(output_dir)
|
||||
#base.create_dir(output_dir)
|
||||
|
||||
input_files = []
|
||||
for file in glob.glob(os.path.join(u"" + directory_input, u'*')):
|
||||
input_files.append(file.replace("\\", "/"))
|
||||
|
||||
#print(input_files)
|
||||
temp_dir = os.getcwd().replace("\\", "/") + "/temp"
|
||||
if base.is_dir(temp_dir):
|
||||
base.delete_dir(temp_dir)
|
||||
base.create_dir(temp_dir)
|
||||
|
||||
directory_fonts = directory_x2t + "/sdkjs/common"
|
||||
if not base.is_file(directory_fonts + "/AllFonts.js"):
|
||||
base.cmd_in_dir(directory_x2t, "docbuilder", [], True)
|
||||
|
||||
# # True for fit, False for 100%
|
||||
# isScaleSheetToPage = False
|
||||
#
|
||||
# json_fit_text = "0"
|
||||
# if isScaleSheetToPage:
|
||||
# json_fit_text = "1"
|
||||
#
|
||||
# #json_params += "'fitToWidth':" + json_fit_text + ",'fitToHeight':" + json_fit_text + ","
|
||||
# if isScaleSheetToPage:
|
||||
# json_params = "{'spreadsheetLayout':{'fitToWidth':1,'fitToHeight':1},"
|
||||
# else:
|
||||
# json_params = "{'spreadsheetLayout':{'fitToWidth':0,'fitToHeight':0},"
|
||||
# json_params += "'documentLayout':{'drawPlaceHolders':true,'drawFormHighlight':true,'isPrint':true}}"
|
||||
# json_params = json_params.replace("'", """)
|
||||
|
||||
|
||||
json_params = "{"
|
||||
|
||||
json_params += "'spreadsheetLayout':{"
|
||||
|
||||
# True for fit, False for 100%
|
||||
isScaleSheetToPage = False
|
||||
|
||||
json_fit_text = "0"
|
||||
if isScaleSheetToPage:
|
||||
json_fit_text = "1"
|
||||
|
||||
json_params += "'fitToWidth':" + json_fit_text + ",'fitToHeight':" + json_fit_text + ","
|
||||
|
||||
if True:
|
||||
json_params += "'orientation':'landscape',"
|
||||
|
||||
page_margins = "'pageMargins':{'bottom':10,'footer':5,'header':5,'left':5,'right':5,'top':10}"
|
||||
page_setup = "'pageSetup':{'orientation':1,'width':210,'height':297,'paperUnits':0,'scale':190," \
|
||||
"'printArea':false,'horizontalDpi':600,'verticalDpi':600,'usePrinterDefaults':true,'fitToHeight':1,'fitToWidth':1}"
|
||||
|
||||
json_params += "'sheetsProps':{'0':{'headings':false,'printTitlesWidth':null,'printTitlesHeight':null," + page_margins + "," + page_setup + "}}},"
|
||||
|
||||
json_params += "'documentLayout':{'drawPlaceHolders':true,'drawFormHighlight':true,'isPrint':true},"
|
||||
json_params += "'ignorePrintArea':'false'"
|
||||
json_params += "}"
|
||||
json_params = json_params.replace("'", """)
|
||||
|
||||
if not os.path.exists(directory_output):
|
||||
os.mkdir(directory_output)
|
||||
|
||||
output_len = len(input_files)
|
||||
output_cur = 1
|
||||
for input_file in input_files:
|
||||
if os.path.isdir(input_file):
|
||||
next_dir_name = os.path.basename(input_file)
|
||||
base.cmd("python", ["thumbnails_old.py", directory_x2t, input_file, os.path.join(directory_output, next_dir_name), th_width, th_height])
|
||||
if base.is_dir(temp_dir):
|
||||
base.delete_dir(temp_dir)
|
||||
base.create_dir(temp_dir)
|
||||
continue
|
||||
print("process [" + str(output_cur) + " of " + str(output_len) + "]: " + str(input_file.encode("utf-8")))
|
||||
|
||||
width_page = th_width
|
||||
height_page = th_height
|
||||
|
||||
json_params_file = json_params
|
||||
|
||||
if input_file.lower().endswith('.xlsx'):
|
||||
temp_dir_builder = directory_output + "/temp_builder"
|
||||
if base.is_dir(temp_dir_builder):
|
||||
base.delete_dir(temp_dir_builder)
|
||||
base.create_dir(temp_dir_builder)
|
||||
builder = CDocBuilder()
|
||||
builder.SetTmpFolder(temp_dir_builder)
|
||||
|
||||
builder.OpenFile(input_file)
|
||||
context = builder.GetContext()
|
||||
globalObj = context.GetGlobal()
|
||||
|
||||
cmd = """
|
||||
(function(){
|
||||
Api.getPrintAreaSize = function() {
|
||||
return { Width:0, Height:0 };
|
||||
};
|
||||
var sheet = Api.GetSheets()[0];
|
||||
var usedRange = sheet.GetUsedRange();
|
||||
|
||||
var maxCol = -1;
|
||||
var maxRow = -1;
|
||||
usedRange.ForEach(function (cell) {
|
||||
if (cell.GetRowHeight() === 0 || cell.GetColumnWidth() === 0) {
|
||||
return;
|
||||
}
|
||||
var row0 = cell.GetRow() - 1;
|
||||
var col0 = cell.GetCol() - 1;
|
||||
var hasContent = false;
|
||||
var val = cell.GetValue();
|
||||
if (val !== "" && val !== null && val !== undefined) {
|
||||
hasContent = true;
|
||||
}
|
||||
if (!hasContent) {
|
||||
var formula = cell.GetFormula();
|
||||
if (typeof formula === 'string' && formula.indexOf("=") === 0) {
|
||||
hasContent = true;
|
||||
}
|
||||
}
|
||||
if (hasContent) {
|
||||
if (col0 > maxCol) maxCol = col0;
|
||||
if (row0 > maxRow) maxRow = row0;
|
||||
}
|
||||
});
|
||||
if (maxRow < 0 || maxCol < 0) {
|
||||
return;
|
||||
}
|
||||
var printRange = sheet.GetRange(
|
||||
sheet.GetRangeByNumber(0, 0),
|
||||
sheet.GetRangeByNumber(maxRow, maxCol)
|
||||
);
|
||||
Api.getPrintAreaSize = function() {
|
||||
return { Width:printRange.Width, Height:printRange.Height };
|
||||
};})();
|
||||
"""
|
||||
|
||||
builder.ExecuteCommand(cmd)
|
||||
api = globalObj['Api']
|
||||
|
||||
sizeWH = api.getPrintAreaSize()
|
||||
wPrint = sizeWH.Get("Width").ToDouble()
|
||||
hPrint = sizeWH.Get("Height").ToDouble()
|
||||
|
||||
print("CELL (printSize): " + str(wPrint) + "x" + str(hPrint))
|
||||
|
||||
if (wPrint > 1 and hPrint > wPrint):
|
||||
tmp = width_page
|
||||
width_page = height_page
|
||||
height_page = tmp
|
||||
json_params_file = json_params_file.replace(""width":210,"height":297", ""width":297,"height":210")
|
||||
|
||||
builder.CloseFile()
|
||||
base.delete_dir(temp_dir_builder)
|
||||
|
||||
output_dir = os.path.join(directory_output,
|
||||
os.path.splitext(os.path.basename(input_file))[0])
|
||||
#output_dir = str(output_dir.encode("utf8"))
|
||||
output_dir = abspath(unicode(output_dir))
|
||||
if not os.path.exists(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
output_dir = os.path.join(output_dir,
|
||||
mapping["[" + str(th_width) + "x" + str(th_height) + "]"])
|
||||
#output_dir = str(output_dir.encode("utf8"))
|
||||
#output_dir = dirname(abspath(unicode(output_dir)))
|
||||
output_dir = abspath(unicode(output_dir))
|
||||
if not os.path.exists(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
output_file = output_dir # os.path.join(output_dir, os.path.splitext(os.path.basename(input_file))[0])
|
||||
xml_convert = u"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
xml_convert += u"<TaskQueueDataConvert>"
|
||||
xml_convert += (u"<m_sFileFrom>" + input_file + u"</m_sFileFrom>")
|
||||
xml_convert += (u"<m_sFileTo>" + output_file + u".zip</m_sFileTo>")
|
||||
xml_convert += u"<m_nFormatTo>1029</m_nFormatTo>"
|
||||
xml_convert += (u"<m_sAllFontsPath>" + directory_fonts + u"/AllFonts.js</m_sAllFontsPath>")
|
||||
xml_convert += (u"<m_sFontDir>" + directory_fonts + u"</m_sFontDir>")
|
||||
xml_convert += (u"<m_sJsonParams>" + json_params_file + u"</m_sJsonParams>")
|
||||
xml_convert += u"<m_nDoctParams>1</m_nDoctParams>"
|
||||
xml_convert += u"<m_oThumbnail>"
|
||||
xml_convert += u"<first>false</first>"
|
||||
|
||||
if ((0 != width_page) and (0 != height_page)):
|
||||
xml_convert += u"<aspect>16</aspect>"
|
||||
xml_convert += (u"<width>" + str(width_page) + u"</width>")
|
||||
xml_convert += (u"<height>" + str(height_page) + u"</height>")
|
||||
xml_convert += u"</m_oThumbnail>"
|
||||
xml_convert += u"<m_nDoctParams>1</m_nDoctParams>"
|
||||
xml_convert += (u"<m_sTempDir>" + temp_dir + u"</m_sTempDir>")
|
||||
xml_convert += u"</TaskQueueDataConvert>"
|
||||
base.save_as_script(temp_dir + "/to.xml", [xml_convert])
|
||||
base.cmd_in_dir(directory_x2t, "x2t", [temp_dir + "/to.xml"], True)
|
||||
base.delete_dir(temp_dir)
|
||||
base.create_dir(temp_dir)
|
||||
base.extract_unicode(output_file + u".zip", output_file)
|
||||
if os.path.exists(output_file + ".zip"):
|
||||
try:
|
||||
base.delete_file(output_file + ".zip")
|
||||
except:
|
||||
print("Error in deletin file: ", output_file + ".zip")
|
||||
output_cur += 1
|
||||
#output_file = output_file.replace("\\", "/")
|
||||
#imnames = Path(output_file).glob("*.png")#glob.glob("/" + output_file.replace(":", "") + "/*.png")
|
||||
imnames = [str(pp) for pp in Path(output_file).glob("*.png")]
|
||||
#print(output_file + "/*.png", imnames)
|
||||
#continue
|
||||
if len(imnames) == 0:
|
||||
base.delete_dir(output_file)
|
||||
else:
|
||||
width, height = imagesize.get(imnames[0])
|
||||
print("WxH: ", width, height)
|
||||
if width < height and False: #удалить вертикальные превью
|
||||
base.delete_dir(output_file)
|
||||
|
||||
base.delete_dir(temp_dir)
|
||||
os.chdir(cur_path)
|
||||
5
tools/linux/.gitignore
vendored
Normal file
5
tools/linux/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
qt_build
|
||||
packages_complete
|
||||
python3
|
||||
python3.tar.gz
|
||||
extract.sh
|
||||
@ -6,6 +6,7 @@ import base
|
||||
import os
|
||||
import subprocess
|
||||
import deps
|
||||
import qt_binary_build
|
||||
|
||||
def get_branch_name(directory):
|
||||
cur_dir = os.getcwd()
|
||||
@ -57,12 +58,7 @@ def install_qt():
|
||||
return
|
||||
|
||||
def install_qt_prebuild():
|
||||
url_amd64 = "https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/qt/qt_binary_linux_amd64.7z"
|
||||
base.download(url_amd64, "./qt_amd64.7z")
|
||||
base.extract("./qt_amd64.7z", "./qt_build")
|
||||
base.create_dir("./qt_build/Qt-5.9.9")
|
||||
base.cmd("mv", ["./qt_build/qt_amd64", "./qt_build/Qt-5.9.9/gcc_64"])
|
||||
base.setup_local_qmake("./qt_build/Qt-5.9.9/gcc_64/bin")
|
||||
base.cmd("python3", ["qt_binary_fetch.py", "all"])
|
||||
return
|
||||
|
||||
if not base.is_file("./node_js_setup_14.x"):
|
||||
@ -72,7 +68,7 @@ if not base.is_file("./node_js_setup_14.x"):
|
||||
if not base.is_dir("./qt_build"):
|
||||
print("install qt...")
|
||||
if base.get_env("DO_NOT_USE_PREBUILD_QT") == "1":
|
||||
install_qt()
|
||||
qt_binary_build.install_qt()
|
||||
else:
|
||||
install_qt_prebuild()
|
||||
|
||||
|
||||
5
tools/linux/cmake.sh
Executable file
5
tools/linux/cmake.sh
Executable file
@ -0,0 +1,5 @@
|
||||
wget https://github.com/Kitware/CMake/releases/download/v3.30.0/cmake-3.30.0-linux-x86_64.tar.gz
|
||||
tar -xzf cmake-3.30.0-linux-x86_64.tar.gz -C /opt
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/cmake /usr/local/bin/cmake
|
||||
ln -s /opt/cmake-3.30.0-linux-x86_64/bin/ctest /usr/local/bin/ctest
|
||||
rm cmake-3.30.0-linux-x86_64.tar.gz
|
||||
@ -16,6 +16,7 @@ def install_deps():
|
||||
"build-essential",
|
||||
"ca-certificates",
|
||||
"cmake",
|
||||
"perl",
|
||||
"curl",
|
||||
"git",
|
||||
"glib-2.0-dev",
|
||||
@ -68,7 +69,7 @@ def install_deps():
|
||||
print("OK")
|
||||
base.cmd("sudo", ["apt-get", "-y", "install", "npm", "yarn"], True)
|
||||
base.cmd("sudo", ["npm", "install", "-g", "grunt-cli"])
|
||||
base.cmd("sudo", ["npm", "install", "-g", "@yao-pkg/pkg"])
|
||||
base.cmd("sudo", ["npm", "install", "-g", "@yao-pkg/pkg@6.11.0"])
|
||||
|
||||
# java
|
||||
java_error = base.cmd("sudo", ["apt-get", "-y", "install", "openjdk-11-jdk"], True)
|
||||
|
||||
16
tools/linux/python.sh
Executable file
16
tools/linux/python.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
wget https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/python3.tar.gz
|
||||
wget https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/python/extract.sh
|
||||
|
||||
chmod +x ./extract.sh
|
||||
./extract.sh
|
||||
|
||||
cd ./python3/bin
|
||||
ln -s python3 python
|
||||
cd ../../
|
||||
|
||||
rm ./extract.sh
|
||||
rm ./python3.tar.gz
|
||||
|
||||
|
||||
47
tools/linux/qt_binary_build.py
Executable file
47
tools/linux/qt_binary_build.py
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../scripts')
|
||||
import base
|
||||
import os
|
||||
import subprocess
|
||||
import deps
|
||||
|
||||
def install_qt():
|
||||
# qt
|
||||
if not base.is_file("./qt_source_5.9.9.tar.xz"):
|
||||
base.download("https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/qt/qt-everywhere-opensource-src-5.9.9.tar.xz", "./qt_source_5.9.9.tar.xz")
|
||||
|
||||
if not base.is_dir("./qt-everywhere-opensource-src-5.9.9"):
|
||||
base.cmd("tar", ["-xf", "./qt_source_5.9.9.tar.xz"])
|
||||
|
||||
qt_params = ["-opensource",
|
||||
"-confirm-license",
|
||||
"-release",
|
||||
"-shared",
|
||||
"-accessibility",
|
||||
"-prefix",
|
||||
"./../qt_build/Qt-5.9.9/gcc_64",
|
||||
"-qt-zlib",
|
||||
"-qt-libpng",
|
||||
"-qt-libjpeg",
|
||||
"-qt-xcb",
|
||||
"-qt-pcre",
|
||||
"-no-sql-sqlite",
|
||||
"-no-qml-debug",
|
||||
"-gstreamer", "1.0",
|
||||
"-nomake", "examples",
|
||||
"-nomake", "tests",
|
||||
"-skip", "qtenginio",
|
||||
"-skip", "qtlocation",
|
||||
"-skip", "qtserialport",
|
||||
"-skip", "qtsensors",
|
||||
"-skip", "qtxmlpatterns",
|
||||
"-skip", "qt3d",
|
||||
"-skip", "qtwebview",
|
||||
"-skip", "qtwebengine"]
|
||||
|
||||
base.cmd_in_dir("./qt-everywhere-opensource-src-5.9.9", "./configure", qt_params)
|
||||
base.cmd_in_dir("./qt-everywhere-opensource-src-5.9.9", "make", ["-j", "4"])
|
||||
base.cmd_in_dir("./qt-everywhere-opensource-src-5.9.9", "make", ["install"])
|
||||
return
|
||||
67
tools/linux/qt_binary_fetch.py
Executable file
67
tools/linux/qt_binary_fetch.py
Executable file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append('../../scripts')
|
||||
|
||||
import base
|
||||
|
||||
URL = "https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/qt/"
|
||||
|
||||
SYSROOTS = {
|
||||
"amd64": "qt_binary_5.9.9_gcc_64.7z",
|
||||
"arm64": "qt_binary_5.9.9_gcc_arm64.7z",
|
||||
}
|
||||
|
||||
COMPILERS = {
|
||||
"amd64": "gcc_64",
|
||||
"arm64": "gcc_arm64",
|
||||
}
|
||||
|
||||
def download_and_extract(name):
|
||||
cur_dir = os.getcwd()
|
||||
os.chdir("./qt_build/Qt-5.9.9")
|
||||
archive = SYSROOTS[name]
|
||||
folder = "./" + COMPILERS[name]
|
||||
if (base.is_dir(folder)):
|
||||
base.delete_dir(folder)
|
||||
archive_file = "./" + archive
|
||||
base.download(URL + archive, archive_file)
|
||||
base.extract(archive_file, "./")
|
||||
os.chdir(cur_dir)
|
||||
base.setup_local_qmake("./qt_build/Qt-5.9.9/" + COMPILERS[name] + "/bin")
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: fetch.py [amd64|arm64|all]")
|
||||
sys.exit(1)
|
||||
|
||||
target = sys.argv[1]
|
||||
|
||||
if not base.is_dir("./qt_build/Qt-5.9.9"):
|
||||
base.create_dir("./qt_build/Qt-5.9.9")
|
||||
|
||||
targets = []
|
||||
if ("all" == target):
|
||||
targets.append("amd64")
|
||||
targets.append("arm64")
|
||||
elif ("arm64" == target) and not base.is_os_arm():
|
||||
targets.append("amd64")
|
||||
targets.append(target)
|
||||
else:
|
||||
targets.append(target)
|
||||
|
||||
if (0 == len(targets)):
|
||||
print(f"Unknown target: {target}")
|
||||
print("Valid values: amd64, arm64, all")
|
||||
sys.exit(1)
|
||||
|
||||
for name in targets:
|
||||
download_and_extract(name)
|
||||
|
||||
if "arm64" in targets and not base.is_os_arm():
|
||||
base.move_dir("./qt_build/Qt-5.9.9/gcc_arm64/bin", "./qt_build/Qt-5.9.9/gcc_arm64/_bin")
|
||||
base.copy_dir("./qt_build/Qt-5.9.9/gcc_64/bin", "./qt_build/Qt-5.9.9/gcc_arm64/bin")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
2
tools/linux/sysroot/.gitignore
vendored
Normal file
2
tools/linux/sysroot/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*sysroot*
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../../../scripts')
|
||||
import base
|
||||
import os
|
||||
import shutil
|
||||
import fix_symlinks
|
||||
|
||||
def bash_chroot(command, sysroot):
|
||||
base.cmd2('sudo -S chroot', [sysroot, '/bin/bash -c', '\"' + command + ' \"'])
|
||||
|
||||
|
||||
def download_sysroot():
|
||||
curr_dir = base.get_script_dir(__file__)
|
||||
tmp_sysroot_ubuntu_dir = curr_dir + '/sysroot_ubuntu_1604'
|
||||
|
||||
if os.path.isdir(tmp_sysroot_ubuntu_dir):
|
||||
shutil.rmtree(tmp_sysroot_ubuntu_dir)
|
||||
|
||||
# debootstrap for downloading sysroot
|
||||
base.cmd2('sudo -S apt-get', ['install', 'debootstrap'])
|
||||
|
||||
archive_ubuntu_url = 'http://archive.ubuntu.com/ubuntu/'
|
||||
base.cmd2('sudo -S debootstrap', ['--arch=amd64', 'xenial', tmp_sysroot_ubuntu_dir, archive_ubuntu_url])
|
||||
|
||||
# setup a new sources
|
||||
base.cmd2('sudo -S cp', [curr_dir + '/sources.list', tmp_sysroot_ubuntu_dir + '/etc/apt/sources.list'])
|
||||
|
||||
bash_chroot('apt update -y', tmp_sysroot_ubuntu_dir)
|
||||
bash_chroot('apt upgrade -y', tmp_sysroot_ubuntu_dir)
|
||||
|
||||
apt_libs = ["build-essential"]
|
||||
apt_libs += ["libpthread-stubs0-dev"]
|
||||
apt_libs += ["zlib1g-dev"]
|
||||
apt_libs += ["curl"]
|
||||
apt_libs += ["libc6-dev"]
|
||||
apt_libs += ["glib-2.0-dev"]
|
||||
apt_libs += ["libglu1-mesa-dev"]
|
||||
apt_libs += ["libgtk-3-dev"]
|
||||
apt_libs += ["libpulse-dev"]
|
||||
apt_libs += ["libasound2-dev"]
|
||||
apt_libs += ["libatspi2.0-dev"]
|
||||
apt_libs += ["libcups2-dev"]
|
||||
apt_libs += ["libdbus-1-dev"]
|
||||
apt_libs += ["libicu-dev"]
|
||||
apt_libs += ["libgstreamer1.0-dev"]
|
||||
apt_libs += ["libgstreamer-plugins-base1.0-dev"]
|
||||
apt_libs += ["libx11-xcb-dev"]
|
||||
apt_libs += ["libxcb*"]
|
||||
apt_libs += ["libxi-dev"]
|
||||
apt_libs += ["libxrender-dev"]
|
||||
apt_libs += ["libxss-dev"]
|
||||
apt_libs += ["libxkbcommon-dev"]
|
||||
apt_libs += ["libxkbcommon-x11-dev"]
|
||||
apt_libs += ["libnotify-dev"]
|
||||
apt_libs += ["gtk+-3.0-dev"]
|
||||
|
||||
apt_libs_str = ""
|
||||
for apt_lib in apt_libs:
|
||||
apt_libs_str += apt_lib + " "
|
||||
bash_chroot('apt install -y ' + apt_libs_str, tmp_sysroot_ubuntu_dir)
|
||||
|
||||
# # downloading arm toolchain
|
||||
arm_toolchain_url = 'https://releases.linaro.org/components/toolchain/binaries/5.4-2017.05/aarch64-linux-gnu/'
|
||||
arm_toolchain_tar_filename = 'gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz'
|
||||
arm_toolchain_output_dir = 'gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu'
|
||||
base.cmd2('wget', [arm_toolchain_url + arm_toolchain_tar_filename])
|
||||
base.cmd2('tar', ['-xf', arm_toolchain_tar_filename])
|
||||
base.cmd2('sudo -S rsync', ['-avh', '--progress', curr_dir + '/' + arm_toolchain_output_dir + '/', tmp_sysroot_ubuntu_dir + '/usr/'])
|
||||
shutil.rmtree(arm_toolchain_output_dir)
|
||||
os.remove(arm_toolchain_tar_filename)
|
||||
|
||||
base.cmd2('sudo -S chmod', ['-R', 'o+rwx', tmp_sysroot_ubuntu_dir])
|
||||
|
||||
# fix symlinks
|
||||
fix_symlinks.fix_symlinks(tmp_sysroot_ubuntu_dir)
|
||||
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
download_sysroot()
|
||||
@ -1,4 +1,19 @@
|
||||
set(CMAKE_C_FLAGS $ENV{CFLAGS})
|
||||
set(CMAKE_CXX_FLAGS $ENV{CXXFLAGS})
|
||||
set(CMAKE_C_LINKER_FLAGS $ENV{LDFLAGS})
|
||||
set(CMAKE_CXX_LINKER_FLAGS $ENV{LDFLAGS})
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
set(CMAKE_MAKE_PROGRAM "/usr/bin/make" CACHE FILEPATH "" FORCE)
|
||||
|
||||
set(CMAKE_C_COMPILER $ENV{CC})
|
||||
set(CMAKE_CXX_COMPILER $ENV{CXX})
|
||||
set(CMAKE_AR $ENV{AR})
|
||||
set(CMAKE_RANLIB $ENV{RANLIB})
|
||||
|
||||
set(CMAKE_C_FLAGS "$ENV{CFLAGS}" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS}" CACHE STRING "" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "$ENV{LDFLAGS}" CACHE STRING "" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "$ENV{LDFLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
224
tools/linux/sysroot/fetch.py
Executable file
224
tools/linux/sysroot/fetch.py
Executable file
@ -0,0 +1,224 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append('../../../scripts')
|
||||
|
||||
import base
|
||||
|
||||
URL = "https://github.com/ONLYOFFICE-data/build_tools_data/raw/refs/heads/master/sysroot/"
|
||||
|
||||
SYSROOTS = {
|
||||
"amd64": "ubuntu16-amd64-sysroot.tar.gz",
|
||||
"arm64": "ubuntu16-arm64-sysroot.tar.gz",
|
||||
}
|
||||
|
||||
def patch_linker_scripts(sysroot_path, arch):
|
||||
"""Fix absolute paths in linker scripts to use sysroot-relative paths"""
|
||||
|
||||
# Determine directories to patch
|
||||
lib_dirs = []
|
||||
|
||||
if arch == "arm64":
|
||||
lib_dirs = [
|
||||
os.path.join(sysroot_path, "usr/lib/aarch64-linux-gnu")
|
||||
]
|
||||
elif arch == "amd64":
|
||||
lib_dirs = [
|
||||
os.path.join(sysroot_path, "usr/lib/x86_64-linux-gnu"),
|
||||
os.path.join(sysroot_path, "usr/aarch64-linux-gnu/lib")
|
||||
]
|
||||
else:
|
||||
return
|
||||
|
||||
total_patched = 0
|
||||
|
||||
for lib_dir in lib_dirs:
|
||||
if not os.path.exists(lib_dir):
|
||||
print(f"Warning: {lib_dir} not found, skipping")
|
||||
continue
|
||||
|
||||
print(f"Patching linker scripts in {lib_dir}...")
|
||||
patched_count = 0
|
||||
|
||||
for filename in os.listdir(lib_dir):
|
||||
if not filename.endswith(".so"):
|
||||
continue
|
||||
|
||||
filepath = os.path.join(lib_dir, filename)
|
||||
if not os.path.isfile(filepath):
|
||||
continue
|
||||
|
||||
# Check if it's a text file (linker script)
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Skip if not a linker script
|
||||
if "GROUP" not in content and "INPUT" not in content:
|
||||
continue
|
||||
|
||||
original_content = content
|
||||
|
||||
# STEP 1: Normalize all /usr/lib paths to /lib
|
||||
# ORDER MATTERS - do longest paths first to avoid partial matches
|
||||
|
||||
# For aarch64
|
||||
content = content.replace("/usr/aarch64-linux-gnu/lib/", "/lib/aarch64-linux-gnu/")
|
||||
content = content.replace("/usr/lib/aarch64-linux-gnu/", "/lib/aarch64-linux-gnu/")
|
||||
|
||||
# For x86_64
|
||||
content = content.replace("/usr/x86_64-linux-gnu/lib/", "/lib/x86_64-linux-gnu/")
|
||||
content = content.replace("/usr/lib/x86_64-linux-gnu/", "/lib/x86_64-linux-gnu/")
|
||||
|
||||
# STEP 2: Add = prefix for sysroot-relative paths
|
||||
content = content.replace("/lib/aarch64-linux-gnu/", "=/lib/aarch64-linux-gnu/")
|
||||
content = content.replace("/lib/x86_64-linux-gnu/", "=/lib/x86_64-linux-gnu/")
|
||||
|
||||
# Write back only if changed
|
||||
if content != original_content:
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print(f" Patched: {filename}")
|
||||
patched_count += 1
|
||||
except Exception as e:
|
||||
# Not a text file or other error, skip
|
||||
pass
|
||||
|
||||
total_patched += patched_count
|
||||
print(f"Patched {patched_count} linker scripts in {lib_dir}")
|
||||
|
||||
print(f"Total patched: {total_patched} linker scripts")
|
||||
|
||||
# Create symlinks from /lib to /usr/lib for library resolution
|
||||
create_lib_symlinks(sysroot_path, arch)
|
||||
|
||||
# Fix absolute symlinks to relative ones
|
||||
fix_absolute_symlinks(sysroot_path, arch)
|
||||
|
||||
|
||||
def create_lib_symlinks(sysroot_path, arch):
|
||||
"""Create symlinks from /lib to /usr/lib for library resolution"""
|
||||
print(f"Creating library symlinks in {sysroot_path}...")
|
||||
|
||||
if arch == "arm64":
|
||||
lib_symlink_dir = os.path.join(sysroot_path, "lib/aarch64-linux-gnu")
|
||||
lib_target_dir = os.path.join(sysroot_path, "usr/lib/aarch64-linux-gnu")
|
||||
elif arch == "amd64":
|
||||
lib_symlink_dir = os.path.join(sysroot_path, "lib/x86_64-linux-gnu")
|
||||
lib_target_dir = os.path.join(sysroot_path, "usr/lib/x86_64-linux-gnu")
|
||||
else:
|
||||
return
|
||||
|
||||
# Create /lib/{arch} directory
|
||||
os.makedirs(lib_symlink_dir, exist_ok=True)
|
||||
|
||||
if not os.path.exists(lib_target_dir):
|
||||
print(f" Warning: Target directory {lib_target_dir} does not exist")
|
||||
return
|
||||
|
||||
symlink_count = 0
|
||||
|
||||
# Create symlinks for all files in /usr/lib/{arch}
|
||||
for filename in os.listdir(lib_target_dir):
|
||||
target = os.path.join(lib_target_dir, filename)
|
||||
link = os.path.join(lib_symlink_dir, filename)
|
||||
|
||||
# Skip if symlink already exists
|
||||
if os.path.exists(link) or os.path.islink(link):
|
||||
continue
|
||||
|
||||
# Create relative symlink
|
||||
rel_target = os.path.relpath(target, lib_symlink_dir)
|
||||
try:
|
||||
os.symlink(rel_target, link)
|
||||
symlink_count += 1
|
||||
except OSError as e:
|
||||
print(f" Warning: Could not create symlink {link}: {e}")
|
||||
|
||||
print(f"Created {symlink_count} symlinks in {lib_symlink_dir}")
|
||||
|
||||
|
||||
def fix_absolute_symlinks(sysroot_path, arch):
|
||||
"""Fix absolute symlinks in /usr/lib to use relative paths"""
|
||||
print(f"Fixing absolute symlinks in {sysroot_path}...")
|
||||
|
||||
if arch == "arm64":
|
||||
lib_dir = os.path.join(sysroot_path, "usr/lib/aarch64-linux-gnu")
|
||||
target_lib_dir = "aarch64-linux-gnu"
|
||||
elif arch == "amd64":
|
||||
lib_dir = os.path.join(sysroot_path, "usr/lib/x86_64-linux-gnu")
|
||||
target_lib_dir = "x86_64-linux-gnu"
|
||||
else:
|
||||
return
|
||||
|
||||
if not os.path.exists(lib_dir):
|
||||
print(f" Warning: {lib_dir} not found")
|
||||
return
|
||||
|
||||
fixed_count = 0
|
||||
|
||||
# Find all .so symlinks pointing to /lib/
|
||||
for filename in os.listdir(lib_dir):
|
||||
if not filename.endswith(".so"):
|
||||
continue
|
||||
|
||||
filepath = os.path.join(lib_dir, filename)
|
||||
|
||||
# Check if it's a symlink
|
||||
if not os.path.islink(filepath):
|
||||
continue
|
||||
|
||||
# Get symlink target
|
||||
target = os.readlink(filepath)
|
||||
|
||||
# Check if it's an absolute path starting with /lib/
|
||||
if target.startswith("/lib/"):
|
||||
# Convert to relative path: /lib/... -> ../../../lib/...
|
||||
relative_target = os.path.join("../../..", target[1:]) # Remove leading /
|
||||
|
||||
# Remove old symlink and create new one
|
||||
os.unlink(filepath)
|
||||
os.symlink(relative_target, filepath)
|
||||
|
||||
print(f" Fixed: {filename} -> {relative_target}")
|
||||
fixed_count += 1
|
||||
|
||||
libgcc_usr_symlink = os.path.join(lib_dir, "libgcc_s.so")
|
||||
libgcc_target = os.path.join(sysroot_path, "lib", target_lib_dir, "libgcc_s.so.1")
|
||||
|
||||
if os.path.exists(libgcc_target) and not os.path.exists(libgcc_usr_symlink):
|
||||
absolute_libgcc = os.path.abspath(libgcc_target)
|
||||
os.symlink(absolute_libgcc, libgcc_usr_symlink)
|
||||
fixed_count += 1
|
||||
|
||||
print(f"Fixed {fixed_count} absolute symlinks")
|
||||
|
||||
def download_and_extract(name):
|
||||
archive = SYSROOTS[name]
|
||||
base.download(URL + archive, "./" + archive)
|
||||
base.cmd("tar", ["-xzf", "./" + archive])
|
||||
|
||||
sysroot_name = archive.replace(".tar.gz", "")
|
||||
patch_linker_scripts(sysroot_name, name)
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: fetch.py [amd64|arm64|all]")
|
||||
sys.exit(1)
|
||||
|
||||
target = sys.argv[1]
|
||||
|
||||
if target == "all":
|
||||
for name in SYSROOTS:
|
||||
download_and_extract(name)
|
||||
elif target in SYSROOTS:
|
||||
download_and_extract(target)
|
||||
else:
|
||||
print(f"Unknown target: {target}")
|
||||
print("Valid values: amd64, arm64, all")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,45 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
# change symbolic link to relative paths
|
||||
def fix_symlinks(top_dir='./sysroot_ubuntu_1604'):
|
||||
for root, dirs, files in os.walk(top_dir):
|
||||
for name in files:
|
||||
path = os.path.join(root, name)
|
||||
if not os.path.islink(path):
|
||||
continue
|
||||
try:
|
||||
target = os.readlink(path)
|
||||
except OSError as e:
|
||||
print(f"Error reading link '{path}': {e}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if not target.startswith('/'):
|
||||
continue
|
||||
|
||||
new_target = top_dir + target
|
||||
new_target_rel = os.path.relpath(new_target, os.path.dirname(path))
|
||||
temp_name = f".tmp.{uuid.uuid4().hex}"
|
||||
temp_path = os.path.join(root, temp_name)
|
||||
try:
|
||||
os.symlink(new_target_rel, temp_path)
|
||||
except OSError as e:
|
||||
print(f"Failed to create temporary symlink for '{path}': {e}", file=sys.stderr)
|
||||
continue
|
||||
try:
|
||||
os.replace(temp_path, path)
|
||||
print(f"Updated: {path} -> {new_target_rel}")
|
||||
except OSError as e:
|
||||
print(f"Failed to replace symlink '{path}': {e}", file=sys.stderr)
|
||||
try:
|
||||
os.unlink(temp_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
directory = sys.argv[1]
|
||||
else:
|
||||
directory = './sysroot_ubuntu_1604'
|
||||
fix_symlinks(directory)
|
||||
@ -1,51 +0,0 @@
|
||||
#deb cdrom:[Ubuntu 16.04.2 LTS _Xenial Xerus_ - Release amd64 (20170215.2)]/ xenial main restricted
|
||||
|
||||
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
|
||||
# newer versions of the distribution.
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial main restricted
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial main restricted
|
||||
|
||||
## Major bug fix updates produced after the final release of the
|
||||
## distribution.
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
|
||||
|
||||
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
|
||||
## team. Also, please note that software in universe WILL NOT receive any
|
||||
## review or updates from the Ubuntu security team.
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial universe
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial-updates universe
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-updates universe
|
||||
|
||||
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
|
||||
## team, and may not be under a free licence. Please satisfy yourself as to
|
||||
## your rights to use the software. Also, please note that software in
|
||||
## multiverse WILL NOT receive any review or updates from the Ubuntu
|
||||
## security team.
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial multiverse
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial multiverse
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial-updates multiverse
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-updates multiverse
|
||||
|
||||
## N.B. software from this repository may not have been tested as
|
||||
## extensively as that contained in the main release, although it includes
|
||||
## newer versions of some applications which may provide useful features.
|
||||
## Also, please note that software in backports WILL NOT receive any review
|
||||
## or updates from the Ubuntu security team.
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse
|
||||
# deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse
|
||||
|
||||
## Uncomment the following two lines to add software from Canonical's
|
||||
## 'partner' repository.
|
||||
## This software is not part of Ubuntu, but is offered by Canonical and the
|
||||
## respective vendors as a service to Ubuntu users.
|
||||
# deb http://archive.canonical.com/ubuntu xenial partner
|
||||
# deb-src http://archive.canonical.com/ubuntu xenial partner
|
||||
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security main restricted
|
||||
# deb-src http://security.ubuntu.com/ubuntu xenial-security main restricted
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security universe
|
||||
# deb-src http://security.ubuntu.com/ubuntu xenial-security universe
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security multiverse
|
||||
# deb-src http://security.ubuntu.com/ubuntu xenial-security multiverse
|
||||
17
tools/linux/sysroot/system-aarch64.toolchain.cmake
Normal file
17
tools/linux/sysroot/system-aarch64.toolchain.cmake
Normal file
@ -0,0 +1,17 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
|
||||
|
||||
set(CMAKE_C_LINKER aarch64-linux-gnu-ld)
|
||||
set(CMAKE_CXX_LINKER aarch64-linux-gnu-ld)
|
||||
|
||||
set(CMAKE_AR aarch64-linux-gnu-ar)
|
||||
set(CMAKE_RANLIB aarch64-linux-gnu-ranlib)
|
||||
set(CMAKE_STRIP aarch64-linux-gnu-strip)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
Reference in New Issue
Block a user