your visual update studio source please para open not includepath found errors detected configurar compilar como code cannot c++ visual-studio gcc visual-c++ iostream

c++ - visual - gcc: tira las funciones no utilizadas



visual studio code c++ (1)

Intente -Wl,--strip-all información de depuración y de símbolos de estática libstdc ++ a través de -Wl,--strip-all . Esto redujo mi ejecutable de 9M a 670K en Cygwin (13x) y de 6M a 80K en Ubuntu (80x).

Noté que a veces, incluso si no uso iostream y las bibliotecas de E / S relacionadas, mis archivos binarios producidos por Mingw todavía eran demasiado grandes.

Por ejemplo, escribí un código para usar vector y cstdio solo y lo -O2 -flto con -O2 -flto , ¡mi programa puede tener un tamaño de hasta 2 MB! nm main.exe > e.txt y me sorprendió ver todas las funciones relacionadas con iostream en él.

Después de -ffunction-sections -Wl,-gc-sections Google, aprendí a usar -ffunction-sections -Wl,-gc-sections , que reduce el tamaño del programa de 2MB a ~ 300KB (si tiene -s , 100 + KB). ¡Excelente!

Para probar aún más el efecto de -ffunction-sections -Wl,-gc-sections , aquí hay otro código:

#include <cstdio> #include <vector> #include <tuple> #include <algorithm> #include <chrono> #include <windows.h> #undef min struct Point { int x, y; }; constexpr int length = 5; constexpr int half_length() { return length & 1 ? length : length - 1; } template<class F> int func_template(F&& f) { #ifdef _MSC_VER puts(__FUNCSIG__); #else puts(__PRETTY_FUNCTION__); #endif printf("/n"); return f(); } struct fake_func { int operator()() const { return 59; }; }; template<class F, class... Args> int pass_args(F&& f, Args&&... args) { #ifdef _MSC_VER puts(__FUNCSIG__); #else puts(__PRETTY_FUNCTION__); #endif printf("/n"); return f(std::forward<Args>(args)...); } template<class T> T min(T x) { return x; } template<class T, class... Args> T min(T x, Args... args) { T y = min(args...); return x < y ? x : y; } void type_verifier(int x) { printf("%dd ", x); } void type_verifier(char x) { printf("''%c'' ", x); } void type_verifier(double x) { printf("%lff ", x); } template<class T> void type_verifier(T x) { printf("unknown "); } template<class T, class... Args> void type_verifier(T x, Args... args) { type_verifier(x); type_verifier(args...); } int bufLen; char buf[100]; template<class... Args> inline int send(Args... args) { bufLen = sprintf(buf, std::forward<Args>(args)...); return bufLen; } namespace std { inline namespace v1 { void func() { printf("I am v1/n"); } } namespace v2 { void func() { printf("I am v2/n"); } } } int main() { std::vector<int> v {1, 2, 3, 4, 5}; for (auto &i : v) printf("%d ", i); printf("/n"); Point p {1, 2}; printf("%d %d/n", p.x, p.y); auto t = std::make_tuple("Hello World", 12); printf("%s %d/n", std::get<0>(t), std::get<1>(t)); int a, b; auto f = []() { return std::make_tuple(1, 2); }; std::tie(a, b) = f(); printf("%d %d/n", a, b); //int test_constexpr[half_length() + 4]; int ft = func_template([]{ return 42; }); printf("func_template: %d/n", ft); ft = func_template(fake_func {}); printf("func_template: %d/n", ft); ft = pass_args([](int x, int y) { return x + y; }, 152, 58); printf("pass_args: %d/n", ft); ft = pass_args([](int n, const char *m) { for (int i = 0; i < n; i++) printf("%c ", m[i]); printf("/n"); return 0; }, 5, "Hello"); printf("min: %d/n", min(3, 4, 2, 1, 5)); type_verifier(12, ''A'', 0.5, "Hello"); printf("/n"); /* send("Hello World"); send("%d", 1); send("%d", "1234"); sprintf(buf, "%d", "123");*/ std::func(); std::v1::func(); std::v2::func(); std::rotate(v.begin(), v.begin() + 2, v.end()); for (auto &i : v) printf("%d ", i); printf("/n"); auto start = std::chrono::steady_clock::now(); std::vector<int> x {2, 4, 2, 0, 5, 10, 7, 3, 7, 1}; printf("insertion sort: "); for (auto &i: x) printf("%d ", i); printf("/n"); // insertion sort for (auto i = x.begin(); i != x.end(); ++i) { std::rotate(std::upper_bound(x.begin(), i, *i), i, i+1); for (auto &j: x) printf("%d ", j); printf("/n"); } std::vector<int> heap {7, 5, 3, 4, 2}; std::make_heap(heap.begin(), heap.end()); std::pop_heap(heap.begin(), heap.end()); printf("Pop heap (%d)/n", heap.back()); heap.pop_back(); heap.push_back(1); std::push_heap(heap.begin(), heap.end()); std::sort_heap(heap.begin(), heap.end()); for (auto &i: heap) printf("%d ", i); printf("/n"); auto end = std::chrono::steady_clock::now(); auto diff = end - start; printf("time: %I64d ms/n", std::chrono::duration_cast<std::chrono::milliseconds>(diff).count()); { auto u = v; std::move_backward(u.begin(), u.begin() + u.size() - 1, u.begin() + u.size()); for (auto &i : u) printf("%d ", i); printf("/n"); } { auto u = v; std::move(u.begin() + 1, u.begin() + u.size(), u.begin()); for (auto &i : u) printf("%d ", i); printf("/n"); } start = std::chrono::steady_clock::now(); Sleep(2000); end = std::chrono::steady_clock::now(); diff = end - start; printf("time: %I64d ms/n", std::chrono::duration_cast<std::chrono::milliseconds>(diff).count()); std::chrono::steady_clock::time_point before; before = std::chrono::steady_clock::now(); Sleep(2000); auto after = std::chrono::steady_clock::now(); printf("%f seconds/n", std::chrono::duration<double>(after - before).count()); return 0; }

Para mi decepción, el programa final es una vez más> 2MB.

Curiosamente, cl.exe elimina cuidadosamente todas las funciones relacionadas con iostream manera consistente, incluso si no cl.exe main.cpp /O2 o cualquier otra marca, solo cl.exe main.cpp . (Para el código anterior, cl.exe produce un binario de 100 + KB).

¿Me perdí alguna otra bandera gcc útil para esto?

Especificación:

  • Mingw-w64 gcc 6.1.0
  • Mingw-w64 gcc 6.2.0
  • Visual Studio 2017 RC
  • Todos los binarios están enlazados estáticamente

Comparar con Linux

Comparé los binarios producidos por gcc 4.9.2 (Linux) y gcc 4.9.3 (mingw-w64) para el código anterior (excepto windows.h Sleep se eliminaron).

Compilar bandera

g++ -o c++11 c++11.cpp -std=c++11 -static-libgcc -static-libstdc++ -ffunction-sections -Wl,-gc-sections -O2

Linux gcc -flto éxito iostream y las funciones sin la necesidad de -flto mientras que Mingw-w64 gcc simplemente no puede hacerlo correctamente.

Windows solo admite el formato PE, mientras que Linux admite el formato ELF, lo que permite que Linux use el enlazador Gold. Tal vez esta es la explicación?

Actualizar

Finalmente, presenté un error en https://sourceforge.net/p/mingw-w64/bugs/578/ . ¡Esperemos que reciba alguna atención!