Każdy zna rozwiązanie, które działa mniej więcej tak:
#include <stdio.h>
#include <gcc.h> /* This .h is what I'm looking for. */
int main (void) {
/* variables declaration (...) */
/* The following line is supposed to be equivalent to:
* $ gcc main.c -o main */
results = gcc_compile_and_link("main.c", "main");
/* Now I want to use the warnings and errors to do something.
* For instance, I'll print them to the console: */
printf("warnings:\n");
for (i=0; i<results.warns_len; i++)
printf("%s\n", results.warings[i].msg);
printf("errors\n");
for (i=0; i<results.errs_len; i++)
printf("%s\n", results.errors[i].msg);
/* free memory and finalize (...) */
return 0;
}
Wiem, że mogę uruchomić polecenie „gcc main.c -o main” w rozwidleniu i przeanalizować dane wyjściowe ... ale szukałem czegoś bardziej „ niezawodnego ”, jak w powyższym przykładzie.
libgccjit
pracuje w tym kierunku, choć będzie to bitwa pod górę: programmers.stackexchange.com/a/323821/124651libgccjit
Wprowadzony w GCC 5 i wciąż jest eksperymentalny od GCC 6.
Dokumenty: https://gcc.gnu.org/onlinedocs/jit/
Powiązane pytania:
źródło
Z gcc nie jest to możliwe, ale może się okazać, że tcc (kompilator C do osadzenia) jest wystarczająco dobry, aby mieć to, co masz na myśli. Dystrybucja zawiera bibliotekę libtcc, która pozwala kompilować, łączyć i uruchamiać kod C „w locie”.
Zauważ, że to tylko dla C, twoje pytanie jest również oznaczone C ++, ale nie widziałem żadnego odpowiednika tcc dla C ++.
źródło
tcc
kompiluje się szybko, ale wcale się nie optymalizuje. Wygenerowany kod jest często 3 do 10 razy wolniejszy niż ten, którygcc -O2
by wyprodukował.Wątpię, żeby było coś lepszego niż rozwidlenie gcc. Możesz rozważyć clang, który jest bardziej zaprojektowany do tego rodzaju zastosowań.
źródło
(Zgaduję, że korzystasz z jakiegoś systemu POSIX, takiego jak Linux lub MacOSX)
Oczywiście powinieneś przyjrzeć się GCCJIT , o czym wspomniał Ciro Santilli . Następnie zbudujesz reprezentację wygenerowanego kodu podobną do AST . Oczywiście możesz zamiast tego rozważyć LLVM lub nawet prostszą bibliotekę JIT, taką jak libjit lub błyskawica GNU (ale
libjit
ilightning
szybko emitują kod, ale emitowany kod jest powolny i niezoptymalizowany).Jednak nadal możesz rozważyć wysłanie kodu C do pliku tymczasowego i wymyślenie jego kompilacji (np. Jako biblioteki współdzielonej, którą później dynamicznie ładowałbyś jako wtyczkę za pomocą dlopen (3) i dlsym (3) ), zobacz tutaj i tutaj dla szczegółów.
Zwróć uwagę na ważny fakt: generowanie zoptymalizowanego kodu wymaga czasu procesora (z GCCJIT, LLVM lub przez uruchomienie
gcc -O2
), ponieważ jest to trudne zadanie. Zatem narzut związany z rozwiązywaniemgcc
procesu (lub używaniem innego kompilatora itp.clang
) Jest znikomy (wrt przy użyciu biblioteki takiej jak GCCJIT lub LLVM).W rzeczywistości, moje doświadczenie (w GCC MELT ) jest takie, że na obecnych komputerach stacjonarnych i laptopach, emitowanie kilkuset linii kodu C i rozwiązywanie ich kompilacji jest wystarczająco szybkie (jedna lub dwie dziesiąte sekundy), aby być kompatybilnym z interakcją użytkownika. Więc dzisiaj możesz rozważyć posiadanie REPL, który by to zrobił. Zobacz także tę pokrewną odpowiedź.
Zajrzyj również do Common Lisp i SBCL, która jest implementacją, która kompiluje się w kod maszynowy przy każdej interakcji REPL.
źródło