metadidomi-builder
v1.6.2812251812
Published
Multi-builder. Support Windows, macOS et Linux en développement.
Maintainers
Readme
�🚀 Multi-Builder Premium
Builder nouvelle génération avec chiffrement de ressources, protection bytecode, obfuscation intelligente et prise en charge Python. Windows maintenant, macOS et Linux en développement.
📑 Table des Matières
- À Propos - Présentation générale
- Installation - Mise en place
- Démarrage Rapide - Premiers pas
- Configuration - Personnalisation
- Modes de Construction - Options de build
- Gestion des Dépendances - Electron et Python
- Protection du Code - Sécurité
- Utilisation de jsMetadidomi - Protection JavaScript
- Packaging Python - Applications Python
- Packaging Android - Applications Android APK
- Comparaison - vs electron-builder
- Roadmap - Futures versions
- Support - Aide et contact
💝 À Propos
Constructeur professionnel pour applications Electron et Python, Android exigeant :
- ✅ Sécurité maximale - Chiffrement AES-256, bytecode, obfuscation
- ✅ Builds reproductibles - 100% déterministe et offline
- ✅ Customisation totale - Contrôle complet du processus
- ✅ Zéro dépendances externes - Tous les outils embarqués
⭐ Soutenir le Projet
Si ce builder vous a aidé, merci de soutenir le développement :
Votre soutien permet de :
- ✅ Développer de nouvelles fonctionnalités
- ✅ Supporter macOS et Linux
- ✅ Améliorer la documentation
- ✅ Corriger les bugs rapidement
🚀 Installation
Dépendances Minimales
Pour le développement : Seuls electron@^39.1.1 et Python 3.11+ sont requis.
npm install� INSTALLATION DES DÉPENDANCES VENDOR
Si lors de l'installation le dossier build_tools/vendor n'est pas présent, suivez ces instructions :
. Téléchargez le fichier vendor.zip depuis :
https://github.com/METADIDOMIOFFICIEL/Metadidomi-Builder/releases/download/1.3.171125/vendor.zi
En suite télécharger le kit Android: https://github.com/METADIDOMIOFFICIEL/Metadidomi-Builder/releases/download/Android.zip/android.zip
💡 Suite :
Vous pouvez aussi extraire manuellement le contenu de vendor.zip dans le dossier build_tools/vendor.
Modules Embarqués - 100% Offline
Toutes les dépendances essentielles sont incluses dans build_tools/vendor/ :
build_tools/vendor/
├── asar/ # Packaging et archivage
├── bytenode/ # Compilation JavaScript → bytecode V8
├── electron-asar/ # ASAR officiel Electron
├── electron-packager/ # Empaquetage Electron
├── javascript-obfuscator/ # Obfuscation de code JS
├── minimist/ # Parsing d'arguments CLI
├── rcedit/ # Édition des ressources Windows
├── sharp/ # Traitement d'images
├── tmp/ # Gestion des fichiers temporaires
├── 7zip-bin/ # Compression 7-Zip
├── nsis/ # Créateur d'installateurs NSIS
├── upx/ # Compression d'exécutables
└── signtool/ # Signature de code Windows (optionnel)Avantages :
- ✅ Reproductibilité totale garantie
- ✅ Indépendance réseau complète
- ✅ Pas de dépendances système externes
- ✅ Builds déterministes
🔐 Signature de Code (Optionnel)
Le builder intègre un système automatique de signature avec deux modes :
Mode 1 : Auto-signé (Défaut - Développement)
- ✅ Généré automatiquement lors du premier build
- 📁 Stocké dans
build_tools/certs/cert-[hash].pfx - 🔑 Mot de passe dans
build_tools/certs/cert-[hash].key - ⚡ Aucune configuration requise
Mode 2 : Certificat Personnalisé (Production)
# Option 1 : Fichier dans le dossier par défaut
# Placer: build_tools/certs/signing.pfx
# Option 2 : Variables d'environnement
$env:PFX_PATH="chemin/vers/certificat.pfx"
$env:PFX_PASS="mot-de-passe-certificat"
# Lancer le build
node build_tools/builder.jsPriorité de signature :
- Module personnalisé
build_tools/signing.js(si présent) signtool.exelocal dansbuild_tools/vendor/signtool/- Windows SDK
signtool.exe(auto-détecté) - Certificat auto-signé (fallback)
⚡ Démarrage Rapide
Pour les Pressés (< 5 min)
# 1. Allez dans votre dossier d'application
cd D:\mon-app
# 2. Lancez le builder
node D:\chemin-vers\metadidomi-builder\build_tools\builder.js
# 3. C'est tout ! ✅
# Résultat: ./dist/MonApp-Setup-1.0.0.exeStructure Minimale Requise
mon-app/
package.json ← Généré automatiquement si manquant
main.js ← Généré automatiquement si manquant
index.html ← Généré automatiquement si manquantSi aucun fichier n'existe, le builder génère une application de démo complète et fonctionnelle ! 🎉
📦 Gestion des Dépendances - Installation et Utilisation
🎯 Concept Global
Le système de dépendances du builder fonctionne selon deux niveaux :
- Dépendances Electron (npm) : Pour votre application JavaScript/Electron
- Dépendances Python : Pour les applications Python créées avec le builder Python
Architecture Générale
Applications Electron Applications Python
↓ ↓
package.json config.py + requirements.txt
↓ ↓
npm install pip install (Python Embeddable)
↓ ↓
node_modules/ Python site-packages/📌 Installation de Dépendances Electron (JavaScript/Node.js)
1️⃣ Ajouter une Dépendance à package.json
Étape 1 : Localiser votre package.json
# Depuis votre dossier d'application
ls package.jsonÉtape 2 : Ajouter une dépendance manuelle (édition directe)
Ouvrez package.json et ajoutez dans la section "dependencies" :
{
"name": "mon-app-electron",
"version": "1.0.0",
"main": "main.js",
"dependencies": {
"electron-store": "^8.1.0", // ← Nouvelle dépendance
"uuid": "^9.0.0", // ← Nouvelle dépendance
"axios": "^1.4.0" // ← Nouvelle dépendance
}
}Étape 3 : Installer les dépendances
# Depuis votre dossier d'application
npm install✅ Résultat : Tous les packages sont téléchargés dans node_modules/
2️⃣ Installer via npm directement (Méthode Rapide)
# Depuis votre dossier d'application
npm install electron-store uuid axiosCela ajoute automatiquement les dépendances à package.json et les installe.
3️⃣ Utiliser une Dépendance dans votre Code
Une fois installée, vous pouvez l'importer et l'utiliser :
Exemple 1 : Utiliser electron-store (Stockage persistant)
// main.js ou n'importe quel fichier JavaScript
const Store = require('electron-store');
const store = new Store();
// Stocker une valeur
store.set('user', {
name: 'Jean',
email: '[email protected]'
});
// Récupérer une valeur
const user = store.get('user');
console.log(user); // { name: 'Jean', email: '[email protected]' }Exemple 2 : Utiliser uuid (Générer des IDs uniques)
// renderer.js ou n'importe quel fichier JavaScript
const { v4: uuidv4 } = require('uuid');
// Générer un ID unique
const userId = uuidv4();
console.log(userId); // ex: "550e8400-e29b-41d4-a716-446655440000"Exemple 3 : Utiliser axios (Requêtes HTTP)
// Faire une requête HTTP
const axios = require('axios');
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Erreur:', error);
});4️⃣ Types de Dépendances
| Type | Commande | Description | Utilisation |
|------|----------|-------------|------------|
| Production | npm install package-name | Code nécessaire à l'exécution | Inclus dans l'app |
| Développement | npm install --save-dev package-name | Outils de build seulement | Exclu de l'app |
✅ Bonnes Pratiques
1. Toujours Versionner les Dépendances
✅ BON: package>=1.0.0
❌ MAUVAIS: package (version flottante)2. Tester Localement Avant de Packager
# Python
.\build_tools\vendor\python_embeddable\python.exe -m pip install -r requirements.txt
python __main__.py
# Node/Electron
npm install
npm start3. Utiliser requirements.txt pour Python
# ✅ BON - Fichier requirements.txt
requests==2.31.0
numpy>=1.24.0
# ❌ MAUVAIS - Pas de fichier requirements.txt4. Documenter les Dépendances
# En haut de chaque fichier
"""
Dépendances requises:
- requests: pour les appels HTTP
- numpy: pour les calculs numériques
"""
import requests
import numpy as np🚀 Mise à Jour des Dépendances
Python
# Voir les dépendances qui peuvent être mises à jour
.\build_tools\vendor\python_embeddable\python.exe -m pip list --outdated
# Mettre à jour une dépendance
.\build_tools\vendor\python_embeddable\python.exe -m pip install --upgrade requests
# Mettre à jour tous les packages
.\build_tools\vendor\python_embeddable\python.exe -m pip install --upgrade -r requirements.txtNode/Electron
# Voir les versions disponibles
npm outdated
# Mettre à jour une dépendance
npm update electron-store
# Mettre à jour tout
npm update🎯 Configuration
Modes de Construction
⭐ Standard (Défaut) - Installateur NSIS
node build_tools/builder.js
# Résultat: ./dist/MonApp-Setup-1.0.0.exeCrée un installateur professionnel avec options d'installation, raccourcis, démarrage automatique.
💾 Portable - Exécutable Autonome
$env:CREATE_PORTABLE_EXE="true"
node build_tools/builder.js
# Résultat: ./dist/MonApp.exe (portable, ~130MB)Exécutable indépendant sans installation requise.
⚡ LITE - Mode Optimisé
$env:LITE_BUILD="true"
node build_tools/builder.js
# Résultat: ./dist/MonApp-Setup-1.0.0.exe (optimisé)
# Rapport: electron-lite-deps-report.txtAnalyse et exclut automatiquement les modules inutiles. Génère un rapport détaillé.
🚫 Sans Installateur
$env:SKIP_INSTALLER="true"
node build_tools/builder.js
# Résultat: Ressources de base seulement🔐 Avec Chiffrement
$env:KEY="votre-clé-secrète"
node build_tools/builder.js⚙️ Compression UPX (Optionnelle)
# Mode rapide (recommandé)
$env:USE_UPX="true"
node build_tools/builder.js
# Mode ultra-brute (très lent, gain maximal)
$env:USE_UPX="true"
$env:UPX_ULTRA_BRUTE="true"
node build_tools/builder.js🔗 Combinaisons Utiles
# Portable + LITE + Chiffrement
$env:CREATE_PORTABLE_EXE="true"
$env:LITE_BUILD="true"
$env:KEY="clé-secrète"
node build_tools/builder.js
# Avec UPX + Signature personnalisée
$env:USE_UPX="true"
$env:PFX_PATH="cert.pfx"
$env:PFX_PASS="mot-de-passe"
node build_tools/builder.jsParamètres Avancés
| Paramètre | Description | Exemple |
|-----------|-------------|---------|
| --app-src <chemin> | Dossier source (défaut: cwd) | --app-src D:\mon-app |
| --output <chemin> | Dossier sortie (défaut: ./dist) | --output D:\dist |
| --out <chemin> | Alias pour --output | --out .\dist |
Fichiers Automatiquement Exclus
node_modules/- Dépendances (à installer dans votre app).git/,.gitignore- Version controldist/,build/,.next/- Anciens builds et caches.env,.env.local- Variables sensibles*.pem,*.key- Certificats privés
Temps de Construction
- Application standard : 2-3 minutes
- Avec LITE : 3-4 minutes (analyse supplémentaire)
- Avec UPX : +2-5 minutes selon la taille
- UPX ultra-brute : +10-30 minutes
Fichiers Générés
dist/MonApp-Setup-X.X.X.exe- Installateur NSIS professionnel (défaut)dist/MonApp.exe- Exécutable portable (siCREATE_PORTABLE_EXE=true)dist/MonApp-lite.exe- Version optimisée (siLITE_BUILD=true)electron-lite-deps-report.txt- Rapport d'optimisation LITE
Architecture de votre Application
Structure Minimale
mon-app/
package.json ← Obligatoire (généré si manquant)
main.js ← Obligatoire (généré si manquant)
preload.js ← Optionnel (généré si manquant)
index.html ← Optionnel (généré si manquant)
assets/
icon.ico ← Optionnel (utilisé dans l'exe et installateur)Structure Recommandée pour Projets Complexes
mon-app/
package.json
main.js
preload.js
index.html
src/
components/
utils/
renderer.js
assets/
icon.ico
images/
data/Important : Le builder traite récursivement TOUS les niveaux de profondeur. Aucune limite !
✨ Fonctionnalités Principales
- ✅ Construction 100% offline - Toutes les dépendances embarquées
- ✅ Reproductibilité - Builds déterministes et vérifiables
- ✅ Chiffrement AES-256-CBC - Ressources protégées
- ✅ Bytecode V8 - Compilation JavaScript → bytecode natif
- ✅ Obfuscation intelligente - Protection du code de fallback
- ✅ Mode LITE - Optimisation automatique des dépendances
- ✅ Compression UPX - Réduction taille exe (optionnel)
- ✅ Signature de code - Automatique ou personnalisée
- ✅ Exécutable portable - Sans installation requise
- ✅ Installateur NSIS - Interface professionnelle
- ✅ Validation HMAC - Intégrité des ressources garantie
- ✅ Watermarking - Métadonnées de build sécurisées
- ✅ Protection preload.js - Injection auto de sécurité contextBridge
- ✅ Empaquetage ASAR récursif - Tous les fichiers inclus à tous les niveaux
- ✅ Gestion Python - Support applications Python standalone
🛡️ Système de Protection Avancé
Le builder intègre un système complet de protection du code avec obfuscation intelligente, chiffrement multi-couches, et anti-analyse.
Deux Modes de Protection
Mode Interactif - Questions guidées pour chaque protection
cd metadidomi-builder/build_tools_py/pyMetadidomi
python pyMetadidomi.pyMode CLI - Automatisé avec arguments
# Presets rapides
python pyMetadidomi.py script.py --light-protection # Léger
python pyMetadidomi.py script.py --medium-protection # Moyen
python pyMetadidomi.py script.py --heavy-protection # Maximal
# Options individuelles
python pyMetadidomi.py script.py --carbon # Obfuscation
python pyMetadidomi.py script.py --junk # Code parasite
python pyMetadidomi.py script.py --anti-vm # Anti-VM
python pyMetadidomi.py script.py --multi-encrypt # Chiffrement multi-couchesProtection pour Electron
node build_tools/builder.js --light-protection
node build_tools/builder.js --medium-protection
node build_tools/builder.js --heavy-protection👉 📖 Documentation complète des protections →
🚀 Utilisation de jsMetadidomi
jsMetadidomi est l'outil de protection JavaScript/HTML du builder. Il obfusque et chiffre votre code avec des couches de sécurité avancées.
Démarrage Rapide
Protéger un Fichier Individuel
# Protéger un fichier JavaScript
node node_modules/metadidomi-builder/build_tools/jsMetadidomi/protect.js mon-script.js dossier-sortie light
# Protéger un fichier HTML
node node_modules/metadidomi-builder/build_tools/jsMetadidomi/protect.js page.html dossier-sortie lightProtéger un Dossier Complet
# Protéger tous les fichiers d'un dossier
node node_modules/metadidomi-builder/build_tools/jsMetadidomi/protect.js src protected-output mediumNiveaux de Protection
| Niveau | Description | Cas d'usage | |--------|-------------|-----------| | light | Obfuscation basique + loader | Développement, tests rapides | | medium | Obfuscation + anti-debug + dead code | Production standard |
Résultat de la Protection
Une fois la protection complétée, vous obtenez :
- 📄 Fichiers protégés - Code obfusqué et chiffré
- 🔑 jsloader.js - Loader de déchiffrement (généré automatiquement)
⚠️ Important : Distribuez le jsloader.js généré avec vos fichiers protégés. Le loader contient les clés et le bytecode nécessaires au déchiffrement.
Utilisation Programmatique
const { obfuscateFile, obfuscateApp } = require('metadidomi-builder/build_tools/jsMetadidomi/jsMetadidomi.js');
// Protéger un fichier
obfuscateFile('mon-script.js', 'dossier-sortie', 'light', true);
// Protéger un dossier
obfuscateApp('src', 'protected-output', 'medium', true);Construction LITE (optimisation)
$env:LITE_BUILD="true"
node build_tools/builder.jsGénère un rapport electron-lite-deps-report.txt avec les modules analysés.
Clé de Chiffrement Personnalisée
$env:KEY="votre-clé-secrète"
node build_tools/builder.jsSi non défini, une clé est générée automatiquement.
Compression UPX
# Mode rapide (défaut)
$env:USE_UPX="true"
node build_tools/builder.js
# Mode ultra-brute (très lent)
$env:USE_UPX="true"
$env:UPX_ULTRA_BRUTE="true"
node build_tools/builder.js🏗️ Architecture du Builder
Le builder suit le principe "zero pollution" :
- ✅ Répertoire du builder : jamais modifié
- ✅ Fichiers générés : dans votre répertoire courant ou
--output - ✅ Isolation : utilise uniquement ses outils internes
- ✅ Nettoyage : les fichiers temporaires sont auto-supprimés
Flux de Compilation
Répertoire courant (votre app)
↓
├─ package.json (généré si manquant)
├─ main.js (généré si manquant)
├─ index.html (généré si manquant)
└─ assets/ (créé si manquant)
↓
Builder (compile, chiffre, empaque, signe)
↓
./dist/
├─ MonApp-Setup-1.0.0.exe (installateur)
└─ MonApp.exe (portable, si demandé)Fichiers Générés par Défaut
| Fichier | Quand ? | Contenu |
|---------|---------|---------|
| package.json | Manquant | Config Electron basique |
| main.js | Manquant | Processus principal |
| preload.js | Manquant | Bridge sécurisé |
| index.html | Manquant | Interface démo |
| assets/icon.ico | (optionnel) | Icône de l'app |
📝 Exemples Pratiques
# Mode simple (depuis votre app)
cd D:\MonApp
node C:\metadidomi-builder\build_tools\builder.js
# Avec source et sortie personnalisées
node build_tools/builder.js --app-src D:\mon-app --output D:\dist
# Avec chiffrement
$env:KEY="ma-clé-secrète"
node build_tools/builder.js --app-src C:\MonApp
# Portable + LITE + UPX
$env:CREATE_PORTABLE_EXE="true"
$env:LITE_BUILD="true"
$env:USE_UPX="true"
node build_tools/builder.jsDépannage
Si le build échoue à cause d'un processus Electron bloqué :
taskkill /F /IM electron.exeErreur : "Dossier source introuvable"
- Vérifiez que le chemin
--app-srcexiste et est correct
Erreur EPERM (permissions) :
- Fermez tous les processus Electron et relancez
🔒 Protection du Code Source
Le builder utilise une approche hybride non-destructive :
✅ Fichiers Source Toujours Intacts
- ✅ Vos fichiers originaux ne sont jamais modifiés
- ✅ Continuez à éditer votre code après chaque build
- ✅ Chaque build utilise une copie temporaire isolée
- ✅ Cleanup automatique des fichiers temporaires
🔄 Traitement Récursif Complet
- ✅ TOUS les fichiers protégés à TOUS les niveaux
- ✅ Aucune limite de profondeur de dossiers
- ✅ Structure complète préservée
- ✅ Même les applications complexes sont totalement protégées
🛡️ Couches de Protection
- Bytecode V8 - Compilation JavaScript → bytecode natif (résiste à la décompilation)
- Fallback Sécurisé - Code de secours si bytecode échoue
- Obfuscation Légère - Protection additionnelle (compatible et stable)
- Chiffrement AES-256 - Ressources et metadata chiffrées
- HMAC Validation - Intégrité vérifiée au lancement
🔐 preload.js - Injection Auto-Sécurité
Le builder vérifie et injecte automatiquement la sécurité contextBridge :
// ✅ Accepté (déjà sécurisé)
contextBridge.exposeInMainWorld('api', {
invoke: (channel) => ipcRenderer.invoke(channel)
});
// ⚠️ Sera enrichi par injection auto du builder
contextBridge.exposeInMainWorld('api', {...});L'injection ajoute automatiquement :
- Liste blanche de modules autorisés
- Validation des canaux IPC
- Gestion des erreurs de sécurité
📊 Comparaison avec electron-builder
- Options d'obfuscation sûres et compatibles
- Pas de transformation agressive du code
- Préserve la stabilité de l'application
📊 Protection multiniveau
Cette approche assure :
- ✅ Sécurité maximale : Protection forte contre l'analyse statique
- ✅ Flexibilité : Vous conservez toujours vos sources
- ✅ Compatibilité : Fonctionne sur tous les environnements
- ✅ Performance : Bytecode offre optimisation d'exécution
- ✅ Maintenance : Facile à mettre à jour et modifier
� Protection Automatique du preload.js - Injection de Sécurité
Le builder inclutt une protection automatique du preload.js pour sécuriser l'exposition des APIs. Si votre preload.js n'a pas la protection contextBridge nécessaire, le builder l'injecte automatiquement avant l'empaquetage.
✅ Vérification et Injection Automatique
Le builder vérifie à chaque build si votre preload.js contient :
- contextBridge.exposeInMainWorld - Exposition sécurisée des APIs
- allowedModules - Liste blanche des modules autorisés
- Validation des canaux IPC - Contrôle d'accès aux communications
🔍 Comment ça fonctionne
AVANT le build :
Vérification du preload.js utilisateur
↓
Détecte-t-on contextBridge.exposeInMainWorld ?
├─ OUI + allowedModules présent → ✅ Accepté (déjà sécurisé)
├─ NON ou allowedModules manquant → Injection nécessaire
│ ↓
│ Injection automatique du code de sécurité
│ ↓
│ ✅ preload.js sécurisé
│
└─ Fichier absent → Création d'un preload.js par défaut sécurisé
Build continue avec preload.js sécurisé → EXE final protégé📝 Exemple : preload.js AVANT injection
const { contextBridge, ipcRenderer } = require('electron');
// ⚠️ INCOMPLET: Pas de protection
contextBridge.exposeInMainWorld('electron', {
minimize: () => ipcRenderer.send('minimize-window'),
maximize: () => ipcRenderer.send('maximize-window'),
close: () => ipcRenderer.send('close-window')
});Lors du build, le builder ajoute :
// ... votre code existant ...
// 🔐 SÉCURITÉ AUTO-INJECTÉE: Protection contextBridge
// Cette section a été automatiquement ajoutée par le builder pour sécuriser l'accès aux modules Node.js
// Valider que les modules exposés utilisent une liste blanche
const validateAllowedModules = (name, module) => {
const ALLOWED_MODULES = {
'electron': ['ipcRenderer', 'ipcMain', 'app'],
'path': ['join', 'resolve', 'dirname'],
'fs': ['readFile', 'writeFile'], // Limiter les accès fs
};
if (!ALLOWED_MODULES[name]) {
console.warn(`[SECURITY] Module "${name}" non autorisé dans la liste blanche`);
return false;
}
return true;
};✅ preload.js Complet et Sécurisé
Si votre preload.js contient déjà la protection complète, le builder le détecte et ne double-injecte pas :
const { contextBridge, ipcRenderer } = require('electron');
// 🔐 PROTECTION CONTEXTBRIDGE - Exposer les APIs de manière sécurisée
contextBridge.exposeInMainWorld('api', {
require: (module) => {
// 📋 Liste blanche des modules autorisés
const allowedModules = ['electron', 'path'];
if (allowedModules.includes(module)) {
return require(module);
}
throw new Error(`Module "${module}" non autorisé`);
}
});Résultat du build : ✅ Accepté tel quel, pas de modification
📊 Cas Gérés par le Builder
| Cas | Détection | Action | Résultat |
|-----|-----------|--------|----------|
| preload.js absent | ❌ Fichier manquant | ✅ Création auto | preload.js sécurisé créé |
| preload.js incomplet | ⚠️ contextBridge présent, allowedModules absent | ✅ Injection | Protection ajoutée |
| preload.js complet | ✅ Les deux présents | ✅ Validation | Accepté sans modification |
| preload.js dangereux | ⚠️ Aucune protection détectée | ✅ Injection | Protection complète ajoutée |
🛡️ Protection Injectée
Le code injecté fournit :
- Liste blanche des modules - Seulement les modules autorisés
- Validation des canaux IPC - Seulement les canaux sécurisés
- Gestion des erreurs - Messages de sécurité clairs
- Logging - Traçabilité des accès refusés
🔄 Flux Complet de Build avec Sécurité preload.js
┌─────────────────────────────────────┐
│ 1. Vérification du preload.js │
│ ✅ Détecte contexBridge │
│ ✅ Valide allowedModules │
│ ✅ Injection si nécessaire │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ 2. Protection Récursive │
│ ✅ Tous les fichiers protégés │
│ ✅ À tous les niveaux │
│ ✅ preload.js inclus │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ 3. Empaquetage ASAR Récursif │
│ ✅ preload.js sécurisé inclus │
│ ✅ Structure préservée │
│ ✅ Tous les fichiers présents │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ 4. Chiffrement et EXE Final │
│ ✅ Ressources chiffrées │
│ ✅ preload.js sécurisé │
│ ✅ Application protégée │
└─────────────────────────────────────┘💡 Avantages de l'Injection Automatique
- ✅ Sécurité garantie : Même si vous oubliez la protection
- ✅ Pas de modification des sources : Injection dans la copie temporaire
- ✅ Flexible : Respecte votre code existant s'il est complet
- ✅ Transparent : Vous ne devez rien faire, c'est automatique
- ✅ Production-ready : L'EXE final est sécurisé
⚙️ Configuration Optionnelle
Si vous voulez utiliser un preload.js personnalisé sans injection :
# Assurez-vous que votre preload.js contient :
# 1. contextBridge.exposeInMainWorld(...)
# 2. Une liste blanche de modules autorisés (allowedModules)
# 3. Une validation des accès
# Puis lancez le builder normalement
node build_tools/builder.js
# → Le builder détecte votre protection et ne fait rien📝 Exemple Complet : preload.js Sécurisé
Voici un exemple de preload.js qui sera accepté sans injection :
const { contextBridge, ipcRenderer } = require('electron');
// 🔐 LISTE BLANCHE: Modules autorisés
const ALLOWED_MODULES = {
'electron': ['ipcRenderer', 'ipcMain'],
'path': ['join', 'resolve'],
};
// 🔐 Valider les accès
const validateModule = (module) => {
if (!ALLOWED_MODULES[module]) {
throw new Error(`Module "${module}" non autorisé`);
}
return true;
};
// 🔐 Exposer l'API sécurisée
contextBridge.exposeInMainWorld('api', {
invoke: (channel, data) => {
const ALLOWED_CHANNELS = ['get-data', 'save-file', 'open-dialog'];
if (ALLOWED_CHANNELS.includes(channel)) {
return ipcRenderer.invoke(channel, data);
}
throw new Error(`Canal "${channel}" non autorisé`);
},
require: (module) => {
validateModule(module);
return require(module);
}
});Résultat du build : ✅ Accepté directement, aucune modification
�📦 Empaquetage ASAR Récursif - Gestion Complète de la Hiérarchie
Le builder utilise une approche 100% récursive pour l'empaquetage ASAR, garantissant que TOUS les fichiers de votre application, peu importe leur profondeur dans la hiérarchie des dossiers, sont correctement empaquetés dans l'archive finale.
✅ Traitement Complet de la Structure
L'empaquetage ASAR est entièrement récursif, ce qui signifie:
- ✅ Fichiers à la racine : EMPAQUETÉS
- ✅ Fichiers dans les sous-dossiers (niveau 1) : EMPAQUETÉS
- ✅ Fichiers imbriqués profondément (niveau 2, 3, 4, ...) : EMPAQUETÉS
- ✅ Structure complète préservée dans l'archive
- ✅ Aucune limite de profondeur - Fonctionne avec n'importe quelle complexité
🗂️ Exemple de Structure Complexe
Application Source:
├── main.js (niveau 0 - racine)
├── preload.js (niveau 0 - racine)
├── index.html (niveau 0 - racine)
│
├── src/ (niveau 1)
│ ├── app.js ✅ EMPAQUETÉS
│ ├── config.js
│ │
│ ├── components/ (niveau 2)
│ │ ├── Button.js ✅ EMPAQUETÉS
│ │ ├── Modal.js
│ │ │
│ │ ├── ui/ (niveau 3)
│ │ │ └── Dialog.js ✅ EMPAQUETÉS
│ │ │
│ │ └── common/ (niveau 3)
│ │ ├── Header.js
│ │ ├── Footer.js
│ │ │
│ │ └── layouts/ (niveau 4)
│ │ ├── Main.js ✅ EMPAQUETÉS (même niveau profond !)
│ │ └── Admin.js
│ │
│ └── utils/ (niveau 2)
│ ├── helpers.js ✅ EMPAQUETÉS
│ ├── validators.js
│ │
│ ├── formatters/ (niveau 3)
│ │ ├── date.js
│ │ └── number.js ✅ EMPAQUETÉS
│ │
│ └── common/ (niveau 3)
│ └── constants.js ✅ EMPAQUETÉS
│
├── lib/ (niveau 1)
│ ├── core.js ✅ EMPAQUETÉS
│ ├── engine.js
│ │
│ ├── handlers/ (niveau 2)
│ │ ├── event.js ✅ EMPAQUETÉS
│ │ ├── error.js
│ │ │
│ │ └── middleware/ (niveau 3)
│ │ ├── auth.js
│ │ ├── cors.js
│ │ │
│ │ └── security/ (niveau 4)
│ │ ├── csrf.js ✅ EMPAQUETÉS (profond !)
│ │ └── sanitize.js
│ │
│ └── helpers/ (niveau 2)
│ └── utils.js ✅ EMPAQUETÉS
│
└── assets/ (niveau 1)
├── images/ (niveau 2)
│ ├── logo.png ✅ EMPAQUETÉS
│ └── icons/ (niveau 3)
│ └── app.ico ✅ EMPAQUETÉS
│
├── styles/ (niveau 2)
│ ├── main.css ✅ EMPAQUETÉS
│ └── themes/ (niveau 3)
│ └── dark.css ✅ EMPAQUETÉS
│
└── data/ (niveau 2)
└── config/ (niveau 3)
└── defaults.json ✅ EMPAQUETÉS🔄 Processus d'Empaquetage Récursif
1️⃣ Collecte Récursive
├─ Traverse tous les répertoires à TOUS les niveaux
├─ Collecte chaque fichier trouvé
├─ Respecte les exclusions (node_modules, .git, etc.)
└─ Résultat: Liste COMPLÈTE de tous les fichiers
2️⃣ Création Archive ASAR
├─ Ajoute chaque fichier avec son chemin exact
├─ Préserve la hiérarchie complète des dossiers
├─ Maintient les permissions et métadonnées
└─ Résultat: app.asar contient TOUS les fichiers
3️⃣ Chiffrement des Ressources
├─ Chiffre app.asar → resources.bin (AES-256-CBC)
├─ Stocke métadonnées et clés en sécurité
└─ Résultat: Ressources protégées dans l'EXE
4️⃣ Création EXE Final
├─ Bootstrap déchiffre resources.bin au lancement
├─ Valide HMAC et watermark
├─ Restaure app.asar en mémoire
└─ Résultat: Application 100% fonctionnelle✅ Garanties d'Intégrité
Le builder garantit que :
- Tous les fichiers sont inclus : 100% des fichiers de votre app, à tous les niveaux
- Structure préservée : Les chemins relatifs et hiérarchie sont intacts
- Aucun oubli : Même les fichiers au niveau 5+ sont traités
- Fichiers non protégés exclus : Les cache, node_modules, .git sont correctement exclus
- Taille vérifiée : app.asar contient exactement la taille attendue
🎯 Avantages de l'Approche Récursive
| Aspect | Avantage | |--------|----------| | Complétude | 100% de l'app est protégée, aucun fichier oublié | | Profondeur | Aucune limite - fonctionne avec n'importe quelle complexité | | Flexibilité | Supporte tous les patterns d'organisation (src, lib, components, etc.) | | Performance | Traversée efficace même pour applications très volumineuses | | Fiabilité | Gestion cohérente de tous les types de fichiers | | Maintenance | Facile d'ajouter du code en profondeur - le builder gère automatiquement |
💡 Exemple: Ajout de Nouveaux Fichiers Profonds
Après le premier build, si vous ajoutez de nouveaux fichiers profonds :
// Avant: structure existante
src/
components/
common/
Header.js
// Après: vous ajoutez
src/
components/
common/
layouts/
Main.js ← Nouveau fichier, niveau 4 !
// Lors du build suivant:
✅ Le builder détecte automatiquement et inclut Main.js
✅ Aucune configuration supplémentaire nécessaire
✅ L'application reste protégée complètement🚀 Performance et Optimisation
L'empaquetage récursif est optimisé pour :
- Vitesse : Collecte efficace même pour des milliers de fichiers
- Mémoire : Traitement par streaming pour gros fichiers
- Réseau : 100% offline, aucun téléchargement externe
- Compatibilité : Format ASAR standard, compatible Electron
📊 Comparaison avec electron-builder
| Critère | metadidomi-builder | electron-builder | |---------|-------------------|------------------| | Installation | 100% offline, vendor local | NPM global ou projet | | Dépendances | Minimal (electron) | Nombreuses | | Configuration | Variables env + builder.js | Config JSON/YAML complexe | | Chiffrement ressources | ✅ AES-256 intégré | ❌ Addon requis | | Bytecode protection | ✅ bytenode natif | ❌ Non | | Mode LITE | ✅ Analyse dépendances | ❌ Non | | Build reproducible | ✅ Oui | ⚠️ Partiel |
metadidomi-builder : Optimal pour sécurité maximale, 100% offline, protection bytecode electron-builder : Optimal pour multi-plateforme, configuration simple, communauté large
👉 Choisir metadidomi-builder si : sécurité critique, environnement offline, control total 👉 Choisir electron-builder si : multi-plateforme, setup simple, app standard
� Packaging d'Applications Python
Le builder inclut aussi un système complet de packaging Python via builder.py pour créer des applications Windows standalone avec installateurs NSIS professionnels.
🚀 Démarrage Rapide - Applications Python
Le plus simple - Exécutez le builder Python depuis votre dossier d'application :
# Depuis votre répertoire d'application Python
cd D:\mon-app-python
python D:\chemin-vers\metadidomi-builder\build_tools_py\builder.py
# Résultat: ./dist/MonApp-Setup-1.0.0.exeOu avec options personnalisées :
# Source et sortie personnalisées
python builder.py --app-src D:\mon-app --output D:\dist
# Mode GUI (sans fenêtre console)
python builder.py --gui
# Combiné
python builder.py --app-src D:\mon-app --output D:\dist --gui📋 Structure Minimale d'une Application Python
Le builder détecte automatiquement une application Python valide avec ces fichiers :
mon-app-python/
├── config.py ⭐ Configuration (généré si manquant)
├── __main__.py ⭐ Point d'entrée (généré si manquant)
├── assets/ ⭐ Ressources (créé si manquant)
│ └── icon.ico (optionnel - utilisé dans l'installateur)
└── ...vos autres fichiers✅ Fichiers Requis vs Optionnels
| Fichier | Requis | Description | Auto-généré |
|---------|--------|-------------|-------------|
| config.py | ⭐ | Configuration app (nom, version, auteur) | ✅ Oui |
| __main__.py | ⭐ | Point d'entrée principal | ✅ Oui |
| main.py | ⚠️ | Alternative à __main__.py | ✅ Dépistage auto |
| app.py | ⚠️ | Alternative au point d'entrée | ✅ Dépistage auto |
| assets/ | ❌ | Dossier de ressources | ✅ Créé vide |
| assets/icon.ico | ❌ | Icône Windows (.ico) | ❌ Non |
Priority de détection du point d'entrée : __main__.py → main.py → app.py → run.py → start.py
📝 Exemple : config.py Minimal
# Configuration de l'application
APP_NAME = "MonApp"
VERSION = "1.0.0"
DESCRIPTION = "Application Python"
AUTHOR = "Votre Entreprise"
ENTRY = "__main__"⚠️ Point d'Entrée Unique (IMPORTANT)
Le builder utilise un seul point d'entrée, celui défini dans la clé ENTRY de config.py.
- ✅ Seul le fichier défini dans
ENTRYsera utilisé comme point d'entrée principal - ❌ Les autres fichiers d'entrée potentiels (
main.py,app.py, etc.) seront ignorés et non embarqués dans le launcher - 🔒 Cela garantit qu'il n'y a aucune ambiguïté sur le point d'entrée réel
Exemple :
# Si vous définissez dans config.py:
ENTRY = "app_launcher"
# Alors SEUL app_launcher.py sera utilisé comme point d'entrée
# Les fichiers main.py, __main__.py, app.py seront complètement ignorésComportement du builder :
- Lit la clé
ENTRYdansconfig.py - Cherche le fichier correspondant (ex:
app_launcher.py) - L'embarque dans le launcher compilé
- Exclut tous les autres fichiers Python d'entrée du payload
Cela évite les conflits et les comportements imprévisibles dus à plusieurs points d'entrée.
📝 Exemple : main.py Minimal
#!/usr/bin/env python3
"""
Point d'entrée principal de l'application Python
"""
import sys
def main():
print("MonApp v1.0.0")
print("Application Python construite avec Metadidomi Builder")
if __name__ == "__main__":
main()🎨 Applications Python avec Tkinter (Interface Graphique)
Pour les applications avec interface graphique Tkinter :
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Application Tkinter avec interface graphique
"""
import tkinter as tk
from tkinter import ttk, messagebox
class MonApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("MonApp")
self.geometry("500x300")
self.resizable(False, False)
# UI Elements
label = ttk.Label(self, text="Bienvenue dans MonApp")
label.pack(pady=20)
button = ttk.Button(self, text="Cliquez-moi", command=self.on_click)
button.pack(pady=10)
def on_click(self):
messagebox.showinfo("Info", "Bouton cliqué!")
if __name__ == "__main__":
app = MonApp()
app.mainloop()Builder avec GUI :
# Mode GUI: pas de fenêtre console
python builder.py --gui
# Par défaut: mode console (fenêtre noire reste visible)
python builder.py🔍 Auto-Génération Intelligente
Si vous exécutez le builder dans un dossier vide, il génère automatiquement :
Dossier vide
↓
python builder.py
↓
Génération automatique:
✅ config.py
✅ __main__.py
✅ assets/ (dossier vide)
↓
Fichiers de démo prêts à modifier🎛️ Modes de Compilation
Mode Console (Défaut)
La fenêtre console reste visible quand l'app s'exécute :
python builder.py
# ➜ Fenêtre console visible
# ➜ Idéal pour les apps CLIMode GUI
Compile sans fenêtre console (parfait pour les apps Tkinter) :
python builder.py --gui
# ➜ Pas de fenêtre console
# ➜ Idéal pour les apps GUI🔧 Paramètres Avancés
| Paramètre | Description | Exemple |
|-----------|-------------|---------|
| --app-src <chemin> | Dossier source (défaut: cwd) | --app-src D:\mon-app |
| --output <chemin> | Dossier sortie (défaut: ./dist) | --output D:\dist |
| --out <chemin> | Alias pour --output | --out .\dist |
| --gui | Compiler en mode GUI (pas de console) | --gui |
| --no-pyc | Ne pas compiler les .py en .pyc | --no-pyc |
| --key <clé> | Clé de chiffrement personnalisée | --key ma-clé |
| --python-embed <chemin> | Python embeddable personnalisé | --python-embed D:\python-embed-amd64 |
🐍 Utilisation d'un Python Embeddable Personnalisé
Le paramètre --python-embed permet d'utiliser votre propre distribution Python embeddable au lieu de celle par défaut. Cela est utile pour :
- ✅ Utiliser une version Python différente
- ✅ Utiliser un Python pré-configuré avec vos dépendances
- ✅ Optimiser la taille du package final
- ✅ Builds reproductibles avec un Python maîtrisé
Utilisation :
# Utiliser un Python embeddable personnalisé
python builder.py --python-embed D:\python-embed-amd64
# Combiné avec d'autres paramètres
python builder.py --app-src D:\mon-app --output D:\dist --python-embed D:\python-embed-amd64 --gui
# Via variable d'environnement
$env:PYTHON_EMBED = "D:\python-embed-amd64"
python builder.pyStructure attendue du dossier Python embeddable :
python-embed-amd64/
├── python.exe ← Exécutable Python principal
├── python311.dll ← Librairie Python
├── Lib/ ← Librairies standard Python
├── DLLs/ ← DLLs compilées
├── Scripts/ ← Scripts exécutables
└── site-packages/ ← Packages tiers installésImportant : Assurez-vous que votre dossier Python embeddable contient tous les fichiers standards et que les dépendances requises sont installées dans site-packages/.
💾 Architecture du Packaging Python
Le builder Python utilise une approche 4 étapes pour protéger et packager votre application :
ÉTAPE 1: Archive ZIP Récursive
├─ Collecte TOUS les fichiers de l'app
├─ À TOUS les niveaux de profondeur
└─ Crée une archive ZIP chiffrée
ÉTAPE 2: Chiffrement + HMAC
├─ Chiffrement Fernet (AES-128)
├─ Calcul HMAC-SHA256 (intégrité)
└─ Bundle sécurisé créé
ÉTAPE 3: Bootstrap d'Auto-Extraction
├─ Code Python d'extraction
├─ Déchiffrement automatique
├─ Validation d'intégrité
└─ Exécution du code métier
ÉTAPE 4: Compilateur C Launcher
├─ Injection dynamique du code Python
├─ Compilation du launcher.exe avec GCC
├─ Support console ET GUI
└─ EXE Windows standalone🏗️ Flux Complet de Compilation
Source Python
↓
[Étape 1: Collecte Récursive]
├─ Lit tous les fichiers (.py, config, etc.)
├─ Exclusion auto: __pycache__, .git, node_modules
└─ Crée archive.zip chiffrée
↓
[Étape 2: Chiffrement Fernet]
├─ Chiffre archive.zip → encrypted.bin
├─ Calcule HMAC-SHA256
└─ Clé générée ou personnalisée
↓
[Étape 3: Bootstrap Python]
├─ Code d'extraction créé
├─ Contient clé + HMAC
└─ Sera injecté dans launcher C
↓
[Étape 4: Launcher C + Injection]
├─ Code Python injecté dans launcher.c
├─ Compilation GCC (console ou GUI)
├─ Génère launcher.exe (50-100 KB)
└─ Minimal et autonome
↓
[Étape 5: Installateur NSIS]
├─ Bundle launcher.exe + Python Embeddable
├─ Crée installateur .exe professionnel
└─ Sortie: MonApp-Setup-1.0.0.exe
↓
Installateur Final🐍 Python Embeddable Automatique
Le builder utilise Python Embeddable pour les utilisateurs finaux :
- ✅ Python 3.11.9 autonome (64 bits Windows)
- ✅ Pas d'installation système requise
- ✅ Zéro dépendance extérieure
- ✅ Distribution portable
- ✅ Inclus dans l'installateur NSIS
Localisation : build_tools/vendor/python_embeddable/
🔐 Protection du Code Python
Compilation en Bytecode (optionnel)
- Les fichiers
.pycompilés en.pyc - Protège contre la lecture directe du source
- Les fichiers
Chiffrement Fernet
- Archive ZIP chiffrée en AES-128
- Extraction en mémoire à l'exécution
- Clé générée automatiquement ou personnalisée
Validation HMAC
- Vérification d'intégrité des archives
- Détecte les modifications
- Arrête l'exécution si compromis
Launcher C Minimaliste
- Seulement 50-100 KB
- Code Python injecté dynamiquement
- Exécution directe sans interpréteur externe
📊 Fichiers Générés
dist/
└── MonApp-Setup-1.0.0.exe ← Installateur NSIS professionnel
Contient:
├─ launcher.exe (50-100 KB)
├─ Python 3.11.9 Embeddable (35-40 MB)
├─ Votre code Python (chiffré)
└─ Ressources et assetsTaille finale : 50-150 MB selon la complexité de l'app
🚀 Exemples Complets
Exemple 1 : Application Console Simple
# Structure
mon-app/
config.py
__main__.py
# Build
cd mon-app
python ..\builder.py
# Résultat: ./dist/MonApp-Setup-1.0.0.exeExemple 2 : Application Tkinter GUI
# Structure
mon-app-gui/
config.py
__main__.py ← Interface Tkinter
assets/
icon.ico
# Build (mode GUI pour éviter console)
cd mon-app-gui
python ..\..\builder.py --gui
# Résultat: ./dist/MonApp-Setup-1.0.0.exe (pas de console)Exemple 3 : Application Complexe Multi-Fichiers
# Structure complexe
mon-app/
config.py
__main__.py
utils/
helpers.py
validators.py
lib/
core.py
handlers/
events.py
assets/
icon.ico
data.json
# Build avec sortie personnalisée
python builder.py --app-src D:\mon-app --output D:\dist
# TOUS les fichiers récursivement inclus ✅⚙️ Options Avancées de Compilation
Avec Clé de Chiffrement Personnalisée
# Option 1: Via argument
python builder.py --key "ma-clé-secrète-32-caractères"
# Option 2: Via variable d'environnement
$env:KEY = "ma-clé-secrète-32-caractères"
python builder.pySans Compilation .pyc
python builder.py --no-pyc
# Les .py restent non compilés (plus rapide au build)Combinaisons
# GUI + sortie personnalisée + clé custom
python builder.py --gui --output D:\dist --key "clé-secrète"
# Source custom + GUI + sans .pyc
python builder.py --app-src D:\mon-app --gui --no-pyc🔍 Dépistage et Débogage
Le builder affiche un rapport détaillé du processus :
[builder] 🚀 Metadidomi Python Builder
[builder] Architecture: compatible builder.js (Archive ZIP → Fernet → NSIS)
[builder]
[builder] 📂 Configuration:
[builder] Source: D:\mon-app
[builder] Sortie: D:\mon-app\dist
[builder] Temporaire: D:\mon-app\.build-temp
[builder]
[builder] 📋 Informations de l'application:
[builder] Nom: MonApp
[builder] Version: 1.0.0
[builder] Auteur: Votre Entreprise
[builder]
[builder] 🔑 Clé de chiffrement auto-générée: a1b2c3d4e5f6...
[builder]
[builder] 🛠️ PHASES DE CONSTRUCTION:
[builder]
[builder] 📦 ÉTAPE 1: Empaquetage récursif...
[builder] 📄 config.py (1.2 KB)
[builder] 📄 __main__.py (2.5 KB)
[builder] 📄 utils/helpers.py (3.1 KB)
[builder]
[builder] ✅ Collecte terminée: 15 fichiers
[builder] 📊 Taille totale: 45.2 MB📋 Fichiers Automatiquement Exclus
Le builder exclut toujours ces fichiers/dossiers :
__pycache__/- Cache Python compilé.git/,.gitignore- Version controlnode_modules/- Dépendances Node (si mixed)dist/,build/- Anciens builds.env,.env.local- Variables sensibles*.pyc,*.pyo- Fichiers compilésconfig.build.yaml- Config du builder.build-temp/- Fichiers temporaires
✅ Vérification Post-Build
Après la compilation, vérifiez l'installateur :
# Vérifier la présence du fichier
ls dist/
-Mode LastWriteTime Length Name
----- --------------- ------ ----
-a---- 14/11/2025 10:30 85 MB MonApp-Setup-1.0.0.exe
# Installer et tester
.\dist\MonApp-Setup-1.0.0.exe
# → Fenêtre NSIS d'installation
# → Installation dans Program Files
# → Lancement de MonApp🐛 Dépannage Courant
❌ ERREUR: UnicodeDecodeError dans la console PowerShell
UnicodeDecodeError: 'charmap' codec can't decode byte...✅ SOLUTION: Le builder force UTF-8 automatiquement. Si toujours problématique :
$env:PYTHONIOENCODING = "utf-8"
python builder.py❌ ERREUR: GCC non trouvé (compilation du launcher)
MinGW64 GCC not found✅ SOLUTION: Installez MinGW64 ou modifiez le PATH :
# Via chocolatey
choco install mingw
# OU manuellement via https://www.mingw-w64.org/❌ ERREUR: Python Embeddable non trouvé
Python Embeddable distribution not found✅ SOLUTION: Vérifiez le dossier build_tools/vendor/python_embeddable/
Metadidomi Crone - Générateur d'APK Android
Une solution complète et automatisée pour créer des applications Android (APK) sans besoin de connaissances avancées en Android Studio.
📋 Table des matières
- Installation rapide
- Structure d'un projet
- Créer une nouvelle application
- Configuration de l'application
- Générer l'APK
- Exemples
- Dépannage
- Options avancées
Installation rapide
Prérequis
- Node.js (v14 ou supérieur) - Télécharger
- PowerShell (Windows) ou Bash (Mac/Linux)
- Python 3 (pour la génération d'icônes) - Télécharger
- Pillow (PIL) pour Python :
pip install Pillow
Vérifier l'installation
node --version
python --version
npm --versionInstallation via npm (Recommandé)
Installez metadidomi-builder comme dépendance locale dans votre projet :
npm install metadidomi-builderCréez un package.json à la racine de votre projet :
{
"name": "mon-app-android",
"version": "1.0.0",
"scripts": {
"build": "node node_modules/metadidomi-builder/build_tools/build_apk.js .",
"build-debug": "node node_modules/metadidomi-builder/build_tools/build_apk.js . --fail-on-missing",
"build-restore": "node node_modules/metadidomi-builder/build_tools/build_apk.js . --restore",
"build-icons": "node node_modules/metadidomi-builder/build_tools/generate-icons.js ."
},
"keywords": [
"android",
"apk",
"builder"
],
"author": "Metadidomi",
"license": "MIT",
"dependencies": {
"metadidomi-builder": "file:../metadidomi-builder",
"sharp": "^0.32.0"
}
}Puis installez et lancez le build :
npm install
npm run buildStructure d'un projet
Chaque application Android doit suivre cette structure :
MonApp/
├── app-config.json # Configuration de l'app
├── AndroidManifest.xml # Déclaration Android (généré automatiquement)
├── src/
│ └── com/example/monapp/
│ └── MainActivity.java # Code Java principal
├── res/
│ ├── layout/
│ │ └── activity_main.xml # Interface utilisateur
│ ├── values/
│ │ ├── strings.xml # Textes et traductions
│ │ ├── colors.xml # Couleurs
│ │ └── styles.xml # Styles et thèmes
│ ├── mipmap-hdpi/
│ │ └── ic_launcher.png # Icône de l'app (auto-générée)
│ └── drawable/ # Images supplémentaires (optionnel)
└── build/ # Généré automatiquement (à ignorer)Créer une nouvelle application
Étape 1 : Créer la structure des dossiers
mkdir MonApp\src\com\example\monapp
mkdir MonApp\res\layout
mkdir MonApp\res\values
mkdir MonApp\res\mipmap-hdpiÉtape 2 : Créer app-config.json
Ce fichier contient toutes les informations de votre application.
{
"appName": "MonApp",
"appVersion": "1.0.0",
"appDescription": "Ma première application Android",
"packageName": "com.example.monapp",
"minSdkVersion": 21,
"targetSdkVersion": 34,
"colors": {
"primary": "#2196F3",
"primaryDark": "#1976D2",
"accent": "#FF5722"
}
}Explications des paramètres :
appName: Nom affiché de l'applicationappVersion: Version sémantique (majeur.mineur.patch)packageName: Identifiant unique (format domaine inversé)minSdkVersion: Version Android minimale (21 = Android 5.0)targetSdkVersion: Version Android ciblée (34 = Android 14)colors: Couleurs principales (format hexadécimal)
Étape 3 : Créer l'interface (activity_main.xml)
Fichier : res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="16dp">
<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bienvenue dans MonApp"
android:textSize="24sp"
android:textStyle="bold" />
<Button
android:id="@+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Appuyez-moi"
android:layout_marginTop="16dp" />
</LinearLayout>Étape 4 : Créer les textes (strings.xml)
Fichier : res/values/strings.xml
<resources>
<string name="app_name">MonApp</string>
<string name="app_version">1.0.0</string>
<string name="app_description">Ma première application</string>
<string name="hello_world">Bienvenue</string>
<string name="action_settings">Paramètres</string>
<string name="back">Retour</string>
<string name="forward">Suivant</string>
<string name="reload">Recharger</string>
</resources>Étape 5 : Créer le code Java (MainActivity.java)
Fichier : src/com/example/monapp/MainActivity.java
package com.example.monapp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;
import android.view.View;
import android.util.Log;
public class MainActivity extends Activity {
private static final String TAG = "MonApp";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "MainActivity créée");
Button myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Bouton cliqué!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Bouton cliqué");
}
});
}
}Étape 6 : Ajouter une icône
Placez une image PNG (96x96 pixels) dans res/mipmap/.
Le système générera automatiquement les variantes pour tous les écrans.
Configuration de l'application
app-config.json complet
{
"appName": "MonApp",
"appVersion": "1.0.0",
"appDescription": "Ma première application Android",
"packageName": "com.example.monapp",
"minSdkVersion": 21,
"targetSdkVersion": 34,
"colors": {
"primary": "#2196F3",
"primaryDark": "#1976D2",
"accent": "#FF5722"
},
"minimalRequiredFiles": [
"AndroidManifest.xml",
"res/values/strings.xml",
"res/values/styles.xml",
"res/layout/activity_main.xml"
]
}Générer l'APK
Avec npm
# Build standard
npm run build
# Build avec vérification stricte
npm run build-debug
# Générer les icônes
npm run build-iconsSans sauvegarde
node "metadidomi-builder\build_tools\build_apk.js" "MonApp" --no-backupRestaurer depuis une sauvegarde
node "metadidomi-builder\build_tools\build_apk.js" "MonApp" --restoreRésultat
Après une génération réussie, vous trouverez :
MonApp/
└── MonApp.apk ← Votre application, prête à installer!Fichier de sortie : MonApp/MonApp.apk
Taille typique : 2-5 MB
Exemples
Exemple 1 : Application Compteur
Voir le dossier CounterApp/ pour un exemple complet d'une application de compteur avec :
- Boutons d'incrémentation/décrémentation
- Affichage d'un compteur
- Interface colorée
Exemple 2 : Application Simple
Consultez MyApp/ pour une application de base.
Exemple 3 : Application Avancée
MyApp_Advanced/ contient des fonctionnalités plus complexes.
Dépannage
Erreur : "Aucun fichier Java trouvé"
Cause : Le dossier src/ est vide ou mal structuré.
Solution :
- Vérifiez que
MainActivity.javaexiste danssrc/com/example/monapp/ - Vérifiez le nom du package (doit correspondre à
packageNamedansapp-config.json)
src/
└── com/example/monapp/
└── MainActivity.java ✓ CorrectErreur : "resource string/... not found"
Cause : Une chaîne de caractères référencée n'existe pas dans strings.xml.
Solution :
- Ouvrez
res/values/strings.xml - Ajoutez la chaîne manquante avec son ID correct :
<string name="fragment1">Fragments</string> <string name="action_click">Cliquez ici</string> - Assurez-vous que le nom correspond exactement à celui utilisé dans votre layout XML
Exemple d'erreur rencontrée (CounterApp) :
error: resource string/fragment1 not foundCorrection appliquée :
<!-- res/values/strings.xml -->
<resources>
<string name="app_name">CounterApp</string>
<string name="fragment1">Compteur</string>
<string name="increment">Incrémenter</string>
<string name="decrement">Décrémenter</string>
<string name="reset">Réinitialiser</string>
</resources>Erreur : "cannot find symbol: variable R"
Cause : Les ressources n'ont pas été compilées correctement.
Solution :
- Supprimez le dossier
build/ - Vérifiez que
res/values/strings.xmlest valide (XML bien formé, pas d'accents mal encodés) - Relancez la génération complète
Erreur : "D8 compilation failed" avec "NullPointerException"
Cause : Classes anonymes mal générées lors de la compilation DEX.
Symptômes :
java.lang.NullPointerException: Cannot invoke "String.length()"
Exception in thread "main" java.lang.NullPointerExceptionSolution - Utilisez implements View.OnClickListener au lieu de classes anonymes :
❌ INCORRECT (cause l'erreur D8) :
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
counter++;
updateDisplay();
}
});✅ CORRECT :
public class MainActivity extends Activity implements View.OnClickListener {
private Button incrementBtn, decrementBtn;
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.incrementBtn) counter++;
else if (id == R.id.decrementBtn) counter--;
}
}Pourquoi : D8 (compilateur DEX) a des problèmes avec les classes anonymes imbriquées. Les interfaces nommées sont plus fiables.
Erreur : "cannot find symbol: variable helloText" ou autre ID de ressource
Cause : Le code Java référence un ID qui n'existe pas dans le layout XML.
Symptôme :
error: cannot find symbol
symbol: variable helloText
location: class MainActivitySolution :
- Vérifiez que l'ID existe dans
res/layout/activity_main.xml:<TextView android:id="@+id/helloText" ... /> - Vérifiez que vous utilisez le bon nom en Java :
TextView helloText = (TextView) findViewById(R.id.helloText); - Assurez-vous que l'ID correspond EXACTEMENT (majuscules/minuscules)
Exemple de correction (CounterApp) :
<!-- res/layout/activity_main.xml -->
<LinearLayout ...>
<TextView
android:id="@+id/counterDisplay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0"
android:textSize="72sp" />
<Button
android:id="@+id/incrementBtn"
android:text="Incrémenter" />
</LinearLayout>Erreur : "AndroidManifest.xml not found"
Cause : Fichier de configuration critique manquant ou mal généré.
Solution :
- Vérifiez que
app-config.jsonexiste à la racine du projet - Assurez-vous que le JSON est valide (syntaxe correcte, pas de virgules manquantes)
- Relancez le build avec l'option
--fail-on-missingpour diagnostiquer :node "metadidomi-builder\build_tools\build_apk.js" "MonApp" --fail-on-missing
Erreur : "Fichiers minimums manquants"
Cause : Des fichiers essentiels n'existent pas.
Files requises minimales :
app-config.json→ Configuration de l'appAndroidManifest.xml→ Descripteur (généré automatiquement)res/values/strings.xml→ Textesres/values/styles.xml→ Styles (généré automatiquement)res/layout/activity_main.xml→ Interface utilisateursrc/com/example/monapp/MainActivity.java→ Code principal
Solution :
# Mode diagnostique - affiche les fichiers manquants sans échouer
node "metadidomi-builder\build_tools\build_apk.js" "MonApp"
# Mode strict - échoue si des fichiers manquent
node "metadidomi-builder\build_tools\build_apk.js" "MonApp" --fail-on-missingL'APK n'est pas généré
Cause : Erreur lors de la signature ou de l'assemblage final.
Solution :
- Supprimez le fichier
.keystoredans le dossier du projet :rm "MonApp\.keystore" - Relancez la génération (un nouveau keystore sera créé) :
node "metadidomi-builder\build_tools\build_apk.js" "MonApp"
Erreur : "Invalid app-config.json"
Cause : Fichier de configuration mal formé.
Vérifiez :
{
"appName": "MonApp", // ✓ String valide
"appVersion": "1.0.0", // ✓ Format sémantique (majeur.mineur.patch)
"packageName": "com.example.monapp", // ✓ Format domaine inversé
"minSdkVersion": 21, // ✓ Nombre entier >= 21
"targetSdkVersion": 34, // ✓ Nombre entier
"colors": {
"primary": "#2196F3", // ✓ Couleur hexadécimale valide
"primaryDark": "#1976D2",
"accent": "#FF5722"
}
}Erreur : "Layout XML invalide"
Cause : Syntaxe XML incorrecte dans activity_main.xml.
Vérifiez :
- Les balises ouvrantes et fermantes correspondent (
<LinearLayout>...</LinearLayout>) - Les attributs android: sont valides
- Les IDs sont uniques et bien formatés (
android:id="@+id/monId") - Les textes spéciaux sont échappés (
&,<,>)
Exemple correct :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cliquez-moi" />
</LinearLayout>Erreur : "Icônes manquantes"
Cause : L'icône n'a pas été générée ou redimensionnée correctement.
Solution :
- Placez une image PNG (96x96 pixels minimum) dans
res/drawable/oures/mipmap/ - Exécutez le générateur d'icônes :
node "metadidomi-builder\build_tools\generate-icons.js" "MonApp" - Vérifiez que tous les dossiers mipmap ont été créés :
res/mipmap-mdpi/ic_launcher.png (48x48) res/mipmap-hdpi/ic_launcher.png (72x72) res/mipmap-xhdpi/ic_launcher.png (96x96) res/mipmap-xxhdpi/ic_launcher.png (144x144) res/mipmap-xxxhdpi/ic_launcher.png (192x192)
Erreur : "Package name already exists"
Cause : Un package Android avec le même nom est déjà installé.
Solution :
- Changez le
packageNamedansapp-config.json:"packageName": "com.example.monapp.v2" - Régénérez l'APK
- Ou : désinstallez l'ancienne app avant d'installer la nouvelle
Options avancées
Personnaliser les ressources générées automatiquement
Par défaut, le système génère :
AndroidManifest.xml(descripteur de l'app)res/values/colors.xml(couleurs)res/values/styles.xml(thèmes)
Ces fichiers sont générés à chaque build. Pour les personnaliser, créez-les manuellement et le système les préservera.
Ajouter des ressources personnalisées
res/
├── drawable/ # Images 1x (160 DPI)
├── drawable-hdpi/ # Images 1.5x (240 DPI)
├── drawable-xhdpi/ # Images 2x (320 DPI)
├── drawable-xxhdpi/ # Images 3x (480 DPI)
├── drawable-xxxhdpi/ # Images 4x (640 DPI)
├── font/ 