Używam biblioteki open source, która wydaje się mieć wiele dyrektyw wstępnego przetwarzania do obsługi wielu języków innych niż C.Aby móc przestudiować, co robi biblioteka Chciałbym zobaczyć kod C, który kompiluję po wstępnym przetworzeniu , bardziej jak to, co bym napisał.
Czy gcc (lub inne narzędzie powszechnie dostępne w Linuksie) może odczytać tę bibliotekę, ale wyprowadzić kod C, który ma przetwarzanie wstępne przekonwertowane na cokolwiek i jest również czytelny dla człowieka?
gcc -E
jest bardziej przydatne niż konieczność przepisywania wiersza, aby działałcpp
.Odpowiedzi:
Tak. Przekaż gcc
-E
opcję . Spowoduje to wygenerowanie wstępnie przetworzonego kodu źródłowego.źródło
-o something.o
ty, możesz również chcieć go zmienić na-o something.i
. W przeciwnym razie wstępnie przetworzone dane wyjściowe będą znajdować się w.o
pliku.gcc -E file1.c file2.c ...
cpp
jest preprocesorem.Uruchom,
cpp filename.c
aby wyświetlić wstępnie przetworzony kod, lub lepiej, przekieruj go do pliku z rozszerzeniemcpp filename.c > filename.preprocessed
.źródło
diff
pojawia się żadna różnica w plikach. Wygląda to również na przydatny sposób na wstępne przetwarzanie kodu w poszukiwaniu błędów w makrach. Świetne pytanie i świetna odpowiedź (IALCTHW).Używam gcc jako preprocesora (dla plików html). Robi dokładnie to, co chcesz. Rozszerza dyrektywy "# -", a następnie wyświetla czytelny plik. (ŻADEN z innych preprocesorów C / HTML, których próbowałem, nie robił tego - łączą wiersze, dławią się znakami specjalnymi itp.) Zakładając, że masz zainstalowane gcc, wiersz poleceń to:
gcc -E -xc -P -C -traditional-cpp code_before.cpp> code_after.cpp
(Nie musi to być „cpp”). Doskonały opis tego zastosowania znajduje się pod adresem http://www.cs.tut.fi/~jkorpela/html/cpre.html .
„-Traditional-cpp” zachowuje białe znaki i tabulatory.
źródło
-save-temps
To kolejna dobra opcja, o której należy pamiętać:
main.c
a teraz, oprócz normalnego wyjścia
main.o
, bieżący katalog roboczy zawiera również następujące pliki:main.i
jest żądanym wstępnie posiadanym plikiem zawierającym:main.s
jest bonusem :-) i zawiera wygenerowany zestaw:Jeśli chcesz to zrobić dla dużej liczby plików, rozważ użycie zamiast tego:
który zapisuje pliki pośrednie w tym samym katalogu, co dane
-o
wyjściowe obiektu zamiast w bieżącym katalogu roboczym, unikając w ten sposób potencjalnych konfliktów basename.Zaletą tej opcji
-E
jest to, że można ją łatwo dodać do dowolnego skryptu kompilacji, nie ingerując zbytnio w samą kompilację.Kolejną fajną rzeczą dotyczącą tej opcji jest dodanie
-v
:faktycznie pokazuje używane jawne pliki zamiast brzydkich tymczasowych
/tmp
, więc łatwo jest dokładnie wiedzieć, co się dzieje, co obejmuje etapy wstępnego przetwarzania / kompilacji / asemblacji:Przetestowano w Ubuntu 19.04 amd64, GCC 8.3.0.
źródło
Biegać:
lub
źródło
Załóżmy, że mamy plik Message.cpp lub .c
Kroki 1: Przetwarzanie wstępne (argument -E)
g ++ -E. \ Message.cpp> P1
Wygenerowany plik P1 ma rozwinięte makra, a zawartość pliku nagłówkowego i komentarze są usuwane.
Krok 2: Przetłumacz wstępnie przetworzony plik na zestaw (argument -S). To zadanie jest wykonywane przez kompilator
g ++ -S. \ Message.cpp
Generowany jest asembler (ASM) (Message.s). Zawiera cały kod asemblera.
Krok 3: Przetłumacz kod asemblera na kod obiektowy. Uwaga: Message.s został wygenerowany w kroku 2. g ++ -c. \ Message.s
Generowany jest plik Object o nazwie Message.o. To jest forma binarna.
Krok 4: Łączenie pliku obiektowego. To zadanie jest wykonywane przez konsolidator
g ++. \ Message.o -o MessageApp
Tutaj generowany jest plik exe MessageApp.exe.
źródło