Je développe un binaire ./cc qui agit comme un driver Clang (j’ai réimplémenté le process du driver en code).
Aujourd’hui, la compilation C++ ne se comporte pas comme attendu sur macOS et Linux, notamment à cause de la résolution des librairies/headers C/C++ (libstdc++/libc++), et de flags qui ne devraient pas être passés au mauvais sous-outil.
-
Portabilité
- La compilation doit fonctionner sur macOS et Linux.
-
Auto-détection des headers/libs C/C++ (pas de hardcode)
- Sous Linux et macOS,
./ccdoit trouver automatiquement les include paths et libs standards (C et C++) sans chemins codés en dur.
- Sous Linux et macOS,
-
Fidélité au driver Clang
- Le comportement du driver doit être le plus fidèle possible à celui du driver de Clang (construction de commande, sélection des outils, propagation des flags).
-
Résolution multi-job
- La résolution des libs/headers C/C++ doit être compatible multi-job (plusieurs invocations/compilations en parallèle).
-
Ne pas casser l’existant
- Le code actuel qui gère la compilation en LLVM-IR ne doit pas être cassé (backward compatibility).
Pour compiler du C++ actuellement, ces commandes ne donnent pas le comportement prévu sous Linux et macOS :
./cc -x c++ bar.cpp foo.cppRésultat actuel :
error: unknown argument: '-fskip-odr-check-in-gmf'
error: unknown argument: '-fskip-odr-check-in-gmf'./cc bar.cpp foo.cppRésultat actuel :
error: unknown argument: '-fskip-odr-check-in-gmf'
error: unknown argument: '-fskip-odr-check-in-gmf'La compilation à plusieurs niveaux doit être gérée.
./cc --instrument bar.cpp foo.cpp
./cc --instrument bar.o foo.o./cc bar.cpp foo.cpp
./cc bar.o foo.o- Je veux une solution propre, pas un “quick fix”.
- Chaque correction doit être scalable et maintenable.
- Qualité attendue : séparation claire des responsabilités (par ex. parsing args / détection toolchain / construction commandes / exécution / cache / logs).
- La solution doit être pensée pour évoluer (ajout futur de plateformes, de modes, d’outils, etc.).
- Générer des scripts de test pour couvrir chaque cas listé ci-dessus.
- Inclure des tests macOS + Linux.
- Les tests Linux doivent tourner via un Dockerfile (fourni/généré).
- Les tests doivent valider :
- que la compilation passe,
- que les flags sont routés au bon outil (pas de flag inconnu envoyé au mauvais niveau),
- que les chemins C/C++ standard sont résolus automatiquement,
- que le multi-job ne casse pas la résolution (pas de race conditions, pas de cache global non protégé).
- Proposition d’architecture (modules/composants, responsabilités).
- Modifications de code nécessaires (approche détaillée, points d’intégration).
- Stratégie de détection toolchain/libc++/libstdc++ (macOS vs Linux).
- Suite de tests :
- scripts macOS,
- Dockerfile + scripts Linux,
- commandes exactes exécutées,
- critères de succès/échec.
- Les 4 commandes de compilation (cpp + obj, avec/sans
--instrument) fonctionnent sur macOS et Linux. - Aucune dépendance à des chemins hardcodés pour les headers/libs C/C++.
- Comportement cohérent avec Clang driver (mêmes grandes décisions : frontend, linker, stdlib sélection, etc.).
- Aucun impact négatif sur le mode LLVM-IR existant.
- Tests automatisés disponibles et exécutables (Linux via Dockerfile).
- Parsing args / filtrage :
extractRuntimeConfigconserve les flags--ct-*, les arguments restants restent intacts. - Détection toolchain : nouveau module
toolchain.cpp(résolution du binaire clang, resource dir, mode C++). - Construction driver : utilisation du driver Clang pour produire un
JobPlan(cc1 + autres jobs). - Exécution :
- non‑instrumenté (ToFile) : délègue à
Driver::ExecuteCompilation(fidélité Clang). - instrumenté / ToMemory : cc1 en-process via
Cc1Runner. - linker via
Linker(exécution des jobs non-cc1).
- non‑instrumenté (ToFile) : délègue à
src/compilerlib/compiler.cpp- Suppression des include/sysroot hardcodés.
- Ajout d’un
DriverConfig(toolchain + resource dir + driver-mode C++). - Support du link-only pour
--instrumentet sans instrumentation.
Cc1Runnerutilisé pour les jobs cc1 en mode instrumenté / ToMemory (diagnostics consolidés).- Support des actions
-E/-fsyntax-only(préprocess & syntax-only). -x noneinjecté avant la runtime en mode--instrument.
- Support des actions
src/compilerlib/toolchain.cpp+include/compilerlib/toolchain.hpp- Détection robuste de clang + resource dir.
- Heuristique de mode C++ (sources,
-x,-stdlib, libs, inspection symboles.o/.a).
CMakeLists.txt- Ajout du module toolchain + dépendances LLVM Object.
- Propagation de
CT_CLANG_EXECUTABLE(clang trouvé à la configuration).
- clang path :
CT_CLANG(env) →CT_CLANG_EXECUTABLE(détecté par CMake) →clang-${LLVM_VERSION_MAJOR}→clang/clang++.
- resource dir :
- calcul via
clang::driver::Driver::GetResourcesPath(clang_path)si dispo, - sinon fallback
CLANG_RESOURCE_DIR(CMake).
- calcul via
- mode C++ :
- détecté via
-x c++, extensions.cpp/.cc/.cxx/.mm,-stdlib=,-lstdc++/-lc++, - pour link-only, scan rapide des symboles C++ dans les objets/archives.
- détecté via
- sysroot macOS :
- si
-isysroot/--sysrootabsent, tentative viaxcrun --show-sdk-path.
- si
Script : test/scripts/macos_compile.sh
./cc --instrument foo.cpp bar.cpp./cc --instrument -x c++ -c foo.cpp bar.cpp && ./cc --instrument foo.o bar.o./cc foo.cpp bar.cpp./cc -x c++ -c foo.cpp bar.cpp && ./cc foo.o bar.o
Script : test/scripts/linux_compile.sh
- mêmes commandes que macOS.
Dockerfile : test/docker/Dockerfile
- installe LLVM/Clang 20,
- build + exécute
test/scripts/linux_compile.sh.
# macOS (après build)
bash test/scripts/macos_compile.sh
# Linux local (après build)
bash test/scripts/linux_compile.sh
# Linux via Docker
docker build -f test/docker/Dockerfile .