forked from lix-project/lix
build: remove about 30 cpu-sec of compile time by explicit instantiation
Apparently the fmt contraption has some extremely popular overloads, and
the boost stuff in there gets built approximately infinite times in
every compilation unit.
Change-Id: Ideba2db7d6bf8559e4d91974bab636f5ed106198
This commit is contained in:
parent
422550fd68
commit
4d89844207
14
src/libutil/fmt.cc
Normal file
14
src/libutil/fmt.cc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include "fmt.hh" // IWYU pragma: keep
|
||||||
|
|
||||||
|
template class boost::basic_format<char>;
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
// Explicit instantiation saves about 30 cpu-seconds of compile time
|
||||||
|
template HintFmt::HintFmt(const std::string &, const Uncolored<std::string> &s);
|
||||||
|
template HintFmt::HintFmt(const std::string &, const std::string &s);
|
||||||
|
template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &);
|
||||||
|
|
||||||
|
HintFmt::HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
// Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace.
|
// Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace.
|
||||||
#if __APPLE__ || __FreeBSD__
|
#if __APPLE__ || __FreeBSD__
|
||||||
|
@ -12,6 +11,9 @@
|
||||||
#include <boost/stacktrace.hpp>
|
#include <boost/stacktrace.hpp>
|
||||||
#include "ansicolor.hh"
|
#include "ansicolor.hh"
|
||||||
|
|
||||||
|
// Explicit instantiation in fmt.cc
|
||||||
|
extern template class boost::basic_format<char>;
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,7 +159,9 @@ public:
|
||||||
* Format the given string literally, without interpolating format
|
* Format the given string literally, without interpolating format
|
||||||
* placeholders.
|
* placeholders.
|
||||||
*/
|
*/
|
||||||
HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
|
// Moved out of line because it was instantiating the template below in
|
||||||
|
// every file in the project.
|
||||||
|
HintFmt(const std::string & literal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interpolate the given arguments into the format string.
|
* Interpolate the given arguments into the format string.
|
||||||
|
@ -193,6 +197,11 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Explicit instantiations in fmt.cc
|
||||||
|
extern template HintFmt::HintFmt(const std::string &, const Uncolored<std::string> &s);
|
||||||
|
extern template HintFmt::HintFmt(const std::string &, const std::string &s);
|
||||||
|
extern template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &);
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream & os, const HintFmt & hf);
|
std::ostream & operator<<(std::ostream & os, const HintFmt & hf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ libutil_sources = files(
|
||||||
'experimental-features.cc',
|
'experimental-features.cc',
|
||||||
'file-descriptor.cc',
|
'file-descriptor.cc',
|
||||||
'file-system.cc',
|
'file-system.cc',
|
||||||
|
'fmt.cc',
|
||||||
'git.cc',
|
'git.cc',
|
||||||
'hash.cc',
|
'hash.cc',
|
||||||
'hilite.cc',
|
'hilite.cc',
|
||||||
|
|
|
@ -9,6 +9,31 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T readNum(Source & source)
|
||||||
|
{
|
||||||
|
unsigned char buf[8];
|
||||||
|
source(charptr_cast<char *>(buf), sizeof(buf));
|
||||||
|
|
||||||
|
auto n = readLittleEndian<uint64_t>(buf);
|
||||||
|
|
||||||
|
if (n > (uint64_t) std::numeric_limits<T>::max())
|
||||||
|
throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name());
|
||||||
|
|
||||||
|
return (T) n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template bool readNum<bool>(Source & source);
|
||||||
|
|
||||||
|
template unsigned char readNum<unsigned char>(Source & source);
|
||||||
|
|
||||||
|
template unsigned int readNum<unsigned int>(Source & source);
|
||||||
|
|
||||||
|
template unsigned long readNum<unsigned long>(Source & source);
|
||||||
|
template long readNum<long>(Source & source);
|
||||||
|
|
||||||
|
template unsigned long long readNum<unsigned long long>(Source & source);
|
||||||
|
template long long readNum<long long>(Source & source);
|
||||||
|
|
||||||
void BufferedSink::operator () (std::string_view data)
|
void BufferedSink::operator () (std::string_view data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -450,19 +450,7 @@ inline Sink & operator<<(Sink & sink, const Error & ex)
|
||||||
MakeError(SerialisationError, Error);
|
MakeError(SerialisationError, Error);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T readNum(Source & source)
|
T readNum(Source & source);
|
||||||
{
|
|
||||||
unsigned char buf[8];
|
|
||||||
source(charptr_cast<char *>(buf), sizeof(buf));
|
|
||||||
|
|
||||||
auto n = readLittleEndian<uint64_t>(buf);
|
|
||||||
|
|
||||||
if (n > (uint64_t) std::numeric_limits<T>::max())
|
|
||||||
throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name());
|
|
||||||
|
|
||||||
return (T) n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline unsigned int readInt(Source & source)
|
inline unsigned int readInt(Source & source)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue