Browse Source

Added flutter/rust/android/vscode scripts; updated README file

master
chodak166 1 year ago
parent
commit
91f964c9bb
  1. 44
      .devcontainer/devcontainer.json
  2. 26
      .devcontainer/docker-compose.yml
  3. 1
      .gitignore
  4. 70
      Dockerfile
  5. 50
      README.md
  6. 48
      dev-init/dev-init-android.sh
  7. 38
      dev-init/dev-init-flutter.sh
  8. 30
      dev-init/dev-init-rust.sh
  9. 10
      dev-init/dev.env
  10. 51
      docker-compose.yml
  11. 45
      entrypoint.sh
  12. 48
      sample_projects/flutter_android_demo/build.sh
  13. 18
      sample_projects/flutter_linux_web_demo/build.sh
  14. 41
      sample_projects/flutter_linux_web_demo/lib/main.dart
  15. 20
      sample_projects/flutter_linux_web_demo/pubspec.yaml
  16. 43
      sample_projects/flutter_rust_demo/build.sh

44
.devcontainer/devcontainer.json

@ -0,0 +1,44 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{
"name": "dev-flutter-01",
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": [
"../docker-compose.yml",
"docker-compose.yml"
],
// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "dev-flutter",
// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/projects",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created.
// "postCreateCommand": "cat /etc/os-release",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "devcontainer"
"remoteUser": "developer"
// "postStartCommand": ". /opt/dev-init/dev.env"
}

26
.devcontainer/docker-compose.yml

@ -0,0 +1,26 @@
version: '3.8'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
dev-flutter:
# Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
# folder. Note that the path of the Dockerfile and context is relative to the *primary*
# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
# array). The sample below assumes your primary file is in the root of your project.
#
# build:
# context: .
# dockerfile: .devcontainer/Dockerfile
volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- ..:/workspaces:cached
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity

1
.gitignore vendored

@ -73,3 +73,4 @@ doc/api/
# Built Visual Studio Code Extensions
*.vsix
volumes/

70
Dockerfile

@ -0,0 +1,70 @@
FROM debian:bookworm-20241111-slim
ARG USER_UID=1000
ARG USER_GID=1000
ENV DEV_INIT_DIR=/opt/dev-init
ENV JAVA_VERSION="17"
# Install essential packages
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -y --no-install-recommends \
bash \
ca-certificates \
wget \
curl \
file \
git \
unzip \
xz-utils \
zip \
libglu1-mesa \
cmake cmake-curses-gui \
gcc g++ \
clang \
cmake cmake-curses-gui \
ninja-build pkg-config \
libgtk-3-dev liblzma-dev \
libstdc++-12-dev \
sudo \
micro \
nano \
llvm \
libclang-dev \
libc6:i386 \
libncurses5:i386 \
libstdc++6:i386 \
lib32z1 \
lib32z1-dev \
openjdk-${JAVA_VERSION}-jdk \
libpulse-java \
gosu \
&& rm -rf /var/lib/apt/lists/*
ENV JAVA_HOME /usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64
# Create non-root user with specified UID and GID
RUN groupadd -g ${USER_GID} developer && \
useradd -u ${USER_UID} -g ${USER_GID} -ms /bin/bash developer && \
usermod -aG sudo developer && \
echo "developer:developer" | chpasswd && \
echo 'developer ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
chmod 0440 /etc/sudoers
RUN curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get update -y && apt-get install -y ./google-chrome-stable_current_amd64.deb && \
rm google-chrome-stable_current_amd64.deb
COPY --chown=developer:developer sample_projects /opt/sample_projects
COPY dev-init dev-init $DEV_INIT_DIR
RUN chmod +x $DEV_INIT_DIR/*
# add group 108 (kvm group)
RUN groupadd -g 108 kvm && \
usermod -aG kvm developer
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

50
README.md

@ -1,3 +1,49 @@
# dev-flutter
### Build and configure
Run `docker compose build` to build the dev container. Then inside the container run selected init scripts. E.g.:
```
bash /opt/dev-init/dev-init-flutter.sh
bash /opt/dev-init/dev-init-rust.sh
bash /opt/dev-init/dev-init-android.sh
```
You can skip building the image by pulling `chodak166/dev-flutter`.
Android SDK, gradle, flutter, rust and vscode data should be preserved as configured in compose file. The `/opt/dev-init/dev.env` file is also used by docker compose to setup environment variables. **See docker-compose.yml and .devcontainer/docker-compose.yml for details.**
### Compile and debug the app
Use `flutter create` or sample projects in `/opt/sample_projects` to perform first build and make gradle download dependencies. Then use `flutter run` to run the app.
### Run and debug in VSCode
With `.devcontainer` present in root project just run 'Reopen in container' command (`ctrl+shift+p`) or run `dev-flutter-01` manually with:
```
docker compose run --name dev-flutter-01 -d dev-flutter
```
After connecting to the container install `flutter` and `dart` tools (dart-code.flutter and dart-code.dart-code). Installing toroxx.vscode-avdmanager is also recommended for AVD management.`
AVD UI, flutter commands, dev tools and debug tools should be available from your IDE.
### Run and debug USB device
The `fluter devices` command should identify all connected USB devices along with emulators and system targets with no problem. E.g.:
```
$ flutter devices
Found 5 connected devices:
Armor 3 (mobile) • 3060MF1001017685 • android-arm64 • Android 8.1.0 (API 27)
BV7100 (mobile) • BV7100EEA0015872 • android-arm64 • Android 12 (API 31)
sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64 • Android 14 (API 34) (emulator)
Linux (desktop) • linux • linux-x64 • Debian GNU/Linux 12 (bookworm) 5.15.0-125-generic
Chrome (web) • chrome • web-javascript • Google Chrome 131.0.6778.85
```
export ADB_TRACE=info
In case of any issues try `adb kill-server` and then `adb start-server`. Run `export ADB_TRACE=all` to see verbose output.
You can also check open 5037 port with `fuser 5037/tcp`. Processes using this port can be killed with `fuser -k 5037/tcp`.
Docker image and scripts for flutter/rust/android development in vscode.

48
dev-init/dev-init-android.sh

@ -0,0 +1,48 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$SCRIPT_DIR/dev.env"
: ${ANDROID_SDK_ROOT:=/opt/android-sdk}
: ${ANDROID_VERSION:=34}
: ${ANDROID_BUILD_TOOLS_VERSION:=34.0.0}
: ${ANDROID_ARCHITECTURE:=x86_64}
: ${ANDROID_TOOLS_URL:="http://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"}
if [ ! -d $ANDROID_SDK_ROOT/cmdline-tools ]; then
cd /tmp
# Download and install Android SDK
wget -c $ANDROID_TOOLS_URL -O android-sdk.zip && \
unzip android-sdk.zip -d /tmp && rm android-sdk.zip && \
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/latest && \
mv /tmp/cmdline-tools/* $ANDROID_SDK_ROOT/cmdline-tools/latest/
fi
SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
yes | $SDKMANAGER --licenses
# Install SDK Platform Tools
$SDKMANAGER --install "platform-tools"
$SDKMANAGER --install "platforms;android-$ANDROID_VERSION"
$SDKMANAGER --install "build-tools;$ANDROID_BUILD_TOOLS_VERSION"
$SDKMANAGER --install "system-images;android-${ANDROID_VERSION};google_apis_playstore;${ANDROID_ARCHITECTURE}"
$SDKMANAGER --install "emulator"
# for vscode android plugin:
mkdir -p ~/Library/Android/ ||:
ln -sf /opt/android-sdk/ ~/Library/Android/sdk ||:
# Build demo project
"$ANDROID_SAMPLE_PROJECT/build.sh"
flutter config --android-sdk $ANDROID_SDK_ROOT
flutter emulators --create
echo "Android development environment setup completed successfully!"

38
dev-init/dev-init-flutter.sh

@ -0,0 +1,38 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$SCRIPT_DIR/dev.env"
# Download and setup Flutter
cd /tmp/
curl -v -o flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz
tar xf flutter.tar.xz -C /tmp/
mkdir -p 2>/dev/null ${FLUTTER_ROOT}/ ||:
mv /tmp/flutter/{.*,*} ${FLUTTER_ROOT}/
rm flutter.tar.xz
# Configure git
git config --global --add safe.directory ${FLUTTER_ROOT}
# Configure Flutter
flutter config --no-analytics
flutter config --no-enable-android
flutter config --no-enable-ios
flutter config --no-enable-windows-desktop
flutter config --no-enable-macos-desktop
flutter config --enable-linux-desktop
flutter config --enable-web
# Pre-download binaries and verify installation
flutter precache --linux --web
flutter doctor
flutter --version
# Build demo project
"$FLUTTER_SAMPLE_PROJECT/build.sh"
echo "Flutter development environment setup completed successfully!"

30
dev-init/dev-init-rust.sh

@ -0,0 +1,30 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$SCRIPT_DIR/dev.env"
mkdir -p ${RUSTUP_HOME} ${CARGO_HOME} 2>/dev/null ||:
cd /tmp
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
rustup default stable
rustup update
rustup component add rustfmt clippy
rustup target add wasm32-unknown-unknown
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
cargo install --version 2.6.0 flutter_rust_bridge_codegen
cargo install cargo-expand
cargo install wasm-pack
dart pub global activate fvm
dart --disable-analytics
# Build demo project
"$RUST_SAMPLE_PROJECT/build.sh"
echo "Rust development environment setup completed successfully!"

10
dev-init/dev.env

@ -0,0 +1,10 @@
FLUTTER_ROOT=/opt/flutter
FLUTTER_VERSION=3.22.3
FLUTTER_SAMPLE_PROJECT=/opt/sample_projects/flutter_linux_web_demo
RUST_SAMPLE_PROJECT=/opt/sample_projects/flutter_rust_demo
ANDROID_SAMPLE_PROJECT=/opt/sample_projects/flutter_android_demo
RUSTUP_HOME=/opt/rustup
CARGO_HOME=/opt/cargo
ANDROID_SDK_ROOT=/opt/android-sdk
PATH="${FLUTTER_ROOT}/bin:/opt/cargo/bin:$HOME/.pub-cache/bin:/opt/android-sdk/platform-tools:/opt/android-sdk/emulator:${PATH}"

51
docker-compose.yml

@ -0,0 +1,51 @@
version: '3.8'
services:
dev-flutter:
image: chodak166/dev-flutter
container_name: dev-flutter-01
build:
context: .
args:
USER_UID: ${UID:-1000}
USER_GID: ${GID:-1000}
network_mode: host
environment:
- DISPLAY=${DISPLAY}
- PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native
- TARGET_USER=developer
env_file: dev-init/dev.env
volumes:
- ./volumes/projects:/projects
- ./volumes/flutter:/opt/flutter
- ./volumes/rustup:/opt/rustup
- ./volumes/cargo:/opt/cargo
- ./volumes/android-sdk:/opt/android-sdk
- ./volumes/pub_cache/:/home/developer/.pub-cache
- ./volumes/home_android:/home/developer/.android
- ./volumes/home_gradle:/home/developer/.gradle
- ./volumes/home_vscode-server:/home/developer/.vscode-server
- /tmp/.X11-unix:/tmp/.X11-unix
- $HOME/.Xauthority:/developer/.Xauthority
- ${XDG_RUNTIME_DIR}/pulse:${XDG_RUNTIME_DIR}/pulse
- /run/user/1000/at-spi:/run/user/1000/at-spi #TODO: pass UID?
- /dev/shm:/dev/shm
- ./dev-init:/opt/dev-init # debug
- .:/host # debug
devices:
- /dev/dri:/dev/dri
- /dev/usb:/dev/usb
- /dev/udev:/dev/udev
- /dev/bus:/dev/bus
- /dev/kvm:/dev/kvm
- /dev/snd:/dev/snd
security_opt:
- seccomp:unconfined
privileged: true
cap_add:
- SYS_ADMIN
- NET_ADMIN
- SYS_PTRACE
stdin_open: true
tty: true
init: true

45
entrypoint.sh

@ -0,0 +1,45 @@
#!/bin/bash
# Exit on error
set -e
set -a
. $DEV_INIT_DIR/dev.env
set +a
# Check if TARGET_USER is set
if [ -z "$TARGET_USER" ]; then
echo "ERROR: TARGET_USER environment variable is not set"
exit 1
fi
targetHome=$(getent passwd $TARGET_USER | cut -f6 -d:)
targetUid=$(id -u $TARGET_USER)
if [ -z "$TARGET_USER" ]; then
echo "ERROR: Cannot parse home directory for user $TARGET_USER"
exit 1
fi
# Change ownership of the specified directories
chown -R $TARGET_USER: $ANDROID_SDK_ROOT
chown -R $TARGET_USER: $targetHome/.gradle
chown -R $TARGET_USER: $targetHome/.android
chown -R $TARGET_USER: $targetHome/.pub-cache
chown -R $TARGET_USER: $targetHome/.vscode-server
chown -R $TARGET_USER: /opt/flutter
chown -R $TARGET_USER: /opt/rustup
chown -R $TARGET_USER: /opt/cargo
chown -R $TARGET_USER: /projects
# fix
chown -R $TARGET_USER: /run/user/$targetUid
# chmod 777 /dev/kvm
# If command line arguments are provided, run them as TARGET_USER
# Otherwise, run bash as TARGET_USER
if [ $# -eq 0 ]; then
exec gosu $TARGET_USER bash
else
exec gosu $TARGET_USER "$@"
fi

48
sample_projects/flutter_android_demo/build.sh

@ -0,0 +1,48 @@
#!/bin/bash
set -e # Exit on error
set -x # Print commands being executed
cd "$(dirname "$0")"
# Enable builds
# flutter config --enable-linux-desktop
# flutter config --enable-web
flutter config --enable-android
if [ ! -f lib/main.dart ]; then
flutter create -t app .
flutter_rust_bridge_codegen integrate
fi
# Create project structure (this will add platform-specific files)
# flutter create .
# Get dependencies
# flutter pub get
# Build Rust project first
# cd rust
# cargo build --release
# cd ..
# Generate Flutter Rust Bridge bindings using config file
flutter_rust_bridge_codegen generate
# Build Linux version
# flutter build linux --release
# cp target/release/libnative.so build/linux/x64/release/bundle/lib/
# For web, we need to build the Rust code for wasm target
# cd rust
# rustup target add wasm32-unknown-unknown
# cargo build --release --target wasm32-unknown-unknown
# cd ..
# Build Web version
# flutter build web --release
# flutter_rust_bridge_codegen build-web
flutter build apk --verbose

18
sample_projects/flutter_linux_web_demo/build.sh

@ -0,0 +1,18 @@
#!/bin/bash
cd "$(dirname "$0")"
# Enable Linux and Web builds
flutter config --enable-linux-desktop
flutter config --enable-web
# Create project structure (this will add platform-specific files)
flutter create .
# Get dependencies
flutter pub get
# Build Linux version
flutter build linux --release
# Build Web version
flutter build web --release

41
sample_projects/flutter_linux_web_demo/lib/main.dart

@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Linux & Web Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Flutter Linux & Web Demo'),
),
body: const Center(
child: Text(
'Hello, World!',
style: TextStyle(fontSize: 24),
),
),
);
}
}

20
sample_projects/flutter_linux_web_demo/pubspec.yaml

@ -0,0 +1,20 @@
name: flutter_linux_web_demo
description: A Flutter demo project for Linux and Web platforms
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true

43
sample_projects/flutter_rust_demo/build.sh

@ -0,0 +1,43 @@
#!/bin/bash
cd "$(dirname "$0")"
if [ ! -f lib/main.dart ]; then
flutter create .
flutter_rust_bridge_codegen integrate
fi
set -e # Exit on error
set -x # Print commands being executed
# Enable Linux and Web builds
flutter config --enable-linux-desktop
flutter config --enable-web
# Create project structure (this will add platform-specific files)
# flutter create .
# Get dependencies
flutter pub get
# Build Rust project first
# cd rust
# cargo build --release
# cd ..
# Generate Flutter Rust Bridge bindings using config file
flutter_rust_bridge_codegen generate
# Build Linux version
flutter build linux --release
# cp target/release/libnative.so build/linux/x64/release/bundle/lib/
# For web, we need to build the Rust code for wasm target
# cd rust
# rustup target add wasm32-unknown-unknown
# cargo build --release --target wasm32-unknown-unknown
# cd ..
# Build Web version
# flutter build web --release
flutter_rust_bridge_codegen build-web
cp -r web/pkg build/web/
Loading…
Cancel
Save