# Remote Compilation

Version 2.6.5 provides remote compilation support, through which we can compile code on a remote server, run, and debug remotely. The server can be deployed on Linux/MacOS/Windows to achieve cross-platform compilation, for example: compile and run Windows programs on Linux, and compile and run macOS/Linux programs on Windows.

Compared with ssh remote login and compilation, it is more stable and smoother to use. It will not cause ssh terminal input to be stuck due to network instability, and it can also quickly edit code files locally. We can even seamlessly implement remote compilation in editors and IDEs such as VS/Sublime/VSCode/IDEA without relying on the IDE's own support for remote compilation.

## Start the service

```sh
$ xmake service
<remote_build_server>: listening 0.0.0.0:9091 ..
```

We can also start the service and display detailed log information.

```sh
$ xmake service -vD
<remote_build_server>: listening 0.0.0.0:9091 ..
```

## Start the service in Daemon mode

To start and control the service when in daemon mode, you can issue the following commands:

```sh
$ xmake service --start
$ xmake service --restart
$ xmake service --stop
```

## Configure the server

We first, run the `xmake service` command, it will automatically generate a default `server.conf` configuration file, stored in `~/.xmake/service/server.conf`.

::: tip NOTE
Version 2.6.5, the configuration address is in `~/.xmake/service.conf`. Subsequent versions have made a lot of improvements and separated the configuration file. If you are using version 2.6.6 or above, please use the new configuration file.
:::

Then, we edit it, fixing the server's listening port (optional).

```sh
{
    known_hosts = { },
    logfile = "/Users/ruki/.xmake/service/server/logs.txt",
    remote_build = {
        listen = "0.0.0.0:9691",
        workdir = "/Users/ruki/.xmake/service/server/remote_build"
    },
    tokens = {
        "e438d816c95958667747c318f1532c0f"
    }
}
```

## Configure the client

The client configuration file is in `~/.xmake/service/client.conf`, where we can configure the server address that the client needs to connect to.

::: tip NOTE
Version 2.6.5, the configuration address is in `~/.xmake/service.conf`. Subsequent versions have made a lot of improvements and separated the configuration file. If you are using version 2.6.6 or above, please use the new configuration file.
:::

```sh
{
    remote_build = {
        connect = "127.0.0.1:9691",
        token = "e438d816c95958667747c318f1532c0f"
    }
}
```

## User authorization

::: tip NOTE
Version 2.6.6 and above supports user authentication; version 2.6.5 can only connect anonymously.
:::

Before the actual connection, we briefly introduce several authentication mechanisms currently provided by the services provided by Xmake.

1. Token authentication
2. Password authentication
3. Trusted host verification

### Token Authentication

This is also the default recommended method, which is more secure, more convenient to configure and connect, and does not need to enter a password every time you connect. When we execute the `xmake service` command, a server and client configuration file will be generated by default, and a default token will be automatically generated, so the local direct connection does not require any configuration.

#### Server authentication configuration

The server can configure multiple tokens for authorizing connections to different user hosts, and of course, can share one token.

```sh
{
    known_hosts = { },
    logfile = "/Users/ruki/.xmake/service/server/logs.txt",
    remote_build = {
        listen = "0.0.0.0:9691",
        workdir = "/Users/ruki/.xmake/service/server/remote_build"
    },
    tokens = {
        "e438d816c95958667747c318f1532c0f"
    }
}
```

#### Client Authentication Configuration

The client only needs to add the token on the server to the corresponding client configuration.

```sh
{
    remote_build = {
        connect = "127.0.0.1:9691",
        token = "e438d816c95958667747c318f1532c0f"
    }
}
```

#### Manually generate new token

We can also execute the following command to manually generate a new token and add it to the server configuration ourselves.

```sh
$ xmake service --gen-token
New token a7b9fc2d3bfca1472aabc38bb5f5d612 is generated!
```

### Password authentication

We also provide an authorization mode of password authentication. Compared with token authentication, it requires users to enter a password every time they connect, and can only be connected after the verification is passed.

#### Server authentication configuration

For password authentication, we do not need to manually configure the token, just execute the following command to add a user. During the adding process, the user will be prompted to enter a password.

```sh
$ xmake service --add-user=ruki
Please input user ruki password:
123456
Add user ruki ok!
```

Then, Xmake will generate a new token from the username and password and add it to the token list of the server configuration.

```sh
{
    known_hosts = { },
    logfile = "/Users/ruki/.xmake/service/server/logs.txt",
    remote_build = {
        listen = "0.0.0.0:9691",
        workdir = "/Users/ruki/.xmake/service/server/remote_build"
    },
    tokens = {
        "e438d816c95958667747c318f1532c0f",
        "7889e25402413e93fd37395a636bf942"
    }
}
```

Of course, we can also delete the specified user and password.

```sh
$ xmake service --rm-user=ruki
Please input user ruki password:
123456
Remove user ruki ok!
```

#### Client Authentication Configuration

For the client, we no longer need to set the token of the server. We only need to add the user name that needs to be connected in the connection configuration to enable password authentication. The format is: `user@address:port`

```sh
{
    remote_build = {
        connect = "root@127.0.0.1:9691"
  }
}
```

::: tip NOTE
If the username is removed and the token is not configured, it is anonymous mode. If the server is not configured with a token, the authentication is completely disabled and the connection is made directly.
:::

### Trusted host verification

In addition, in order to further improve security, we also provide server-side trusted host verification. If the server-configured `known_hosts` list is configured with the IP address of the client host that can be connected,
then only these hosts can successfully connect to this server, and other hosts' connections to it will be prompted to be untrusted and refuse the connection, even if token and password authentication are OK.

```sh
{
    logfile = "/Users/ruki/.xmake/service/logs.txt",
    server = {
        tokens = {
            "4b928c7563a0cba10ff4c3f5ca0c8e24"
        },
        known_hosts = { "127.0.0.1", "xx.xx.xx.xx"}
    }
}
```

## Connect to a remote server

Next, we only need to enter the root directory of the project that needs to be compiled remotely, and execute the `xmake service --connect` command to connect.

If it is the token authentication mode, then no additional password input is required, and the connection is directly connected.

```sh
$ xmake create test
$ cd test
$ xmake service --connect
<remote_build_client>: connect 192.168.56.110:9091 ..
<remote_build_client>: connected!
<remote_build_client>: sync files in 192.168.56.110:9091 ..
Scanning files ..
Comparing 3 files ..
    [+]: src/main.cpp
    [+]: .gitignore
    [+]: xmake.lua
3 files has been changed!
Archiving files ..
Uploading files with 1372 bytes ..
<remote_build_client>: sync files ok!
```

If it is password authentication, the user will be prompted to enter the password to continue the connection.

```sh
$ xmake service --connect
Please input user root password:
000000
<remote_build_client>: connect 127.0.0.1:9691 ..
<remote_build_client>: connected!
<remote_build_client>: sync files in 127.0.0.1:9691 ..
Scanning files ..
Comparing 3 files ..
    [+]: xmake.lua
    [+]: .gitignore
    [+]: src/main.cpp
3 files has been changed!
Archiving files ..
Uploading files with 1591 bytes ..
<remote_build_client>: sync files ok!
```

If the password is incorrect, an error message will be displayed.

```sh
$ xmake service --connect
Please input user root password:
123
<remote_build_client>: connect 127.0.0.1:9691 ..
<remote_build_client>: connect 127.0.0.1:9691 failed, user and password are incorrect!
```

## Remote build project

After the connection is successful, we can compile remotely like normal local compilation.

```sh
$ xmake
<remote_build_client>: run xmake in 192.168.56.110:9091 ..
checking for platform... macosx
checking for architecture ... x86_64
checking for Xcode directory ... /Applications/Xcode.app
checking for Codesign Identity of Xcode ... Apple Development: waruqi@gmail.com (T3NA4MRVPU)
checking for SDK version of Xcode for macosx (x86_64) ... 11.3
checking for Minimal target version of Xcode for macosx (x86_64) ... 11.4
[ 25%]: cache compiling.release src/main.cpp
[ 50%]: linking.release test
[100%]: build ok!
<remote_build_client>: run command ok!
```

## Run the target program remotely

We can also run and debug the compiled target program remotely like running and debugging locally.

```sh
$ xmake run
<remote_build_client>: run xmake run in 192.168.56.110:9091 ..
hello world!
<remote_build_client>: run command ok!
```

## Remote Rebuild Project

```sh
$ xmake -rv
<remote_build_client>: run xmake -rv in 192.168.56.110:9091 ..
[ 25%]: cache compiling.release src/main.cpp
/usr/local/bin/ccache /usr/bin/xcrun -sdk macosx clang -c -Qunused-arguments -arch x86_64 -mmacosx-version-min=11.4 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/ MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -o build/.objs/test/macosx/x86_64/release/src/main.cpp.o src /main.cpp
[ 50%]: linking.release test
"/usr/bin/xcrun -sdk macosx clang++" -o build/macosx/x86_64/release/test build/.objs/test/macosx/x86_64/release/src/main.cpp.o -arch x86_64 -mmacosx-version -min=11.4 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -stdlib=libc++ -Wl,-x -lz
[100%]: build ok!
<remote_build_client>: run command ok!
```

## Remote configuration compilation parameters

```sh
$ xmake f --xxx --yy
```

## Manually sync project files

When connecting, the code will be automatically synchronized once, and the code will be changed later. You can execute this command to manually synchronize the changed files.

```sh
$ xmake service --sync
<remote_build_client>: sync files in 192.168.56.110:9091 ..
Scanning files ..
Comparing 3 files ..
    [+]: src/main.cpp
    [+]: .gitignore
    [+]: xmake.lua
3 files has been changed!
Archiving files ..
Uploading files with 1372 bytes ..
<remote_build_client>: sync files ok!
```

## Pull remote files

In version v2.7.1, we added a parameter to pull the remote specified file.
Usually, we can use it to pull the target file after the build and download the compiled library file to the local.

For example:

```sh
xmake service --pull 'build/**' outputdir
```

We can specify the remote path `build/**` to pull all matching files to the local outputdir directory.

## Disconnect from remote

For the current project, disconnect the connection, which only affects the current project, and other projects can still be connected and compiled at the same time.

```sh
$ xmake service --disconnect
<remote_build_client>: disconnect 192.168.56.110:9091 ..
<remote_build_client>: disconnected!
```

## View server log

```sh
$ xmake service --logs
```

## Clean remote service cache and build files

We can also manually clean any caches and build generated files from the remote.

```sh
$ cd projectdir
$ xmake service --clean
```
