Update (and debundle) fmt dependancy

We now support the most recent released version of `fmt` available (at
the time
of committing).

As we no longer patch `fmt` to get it to work within `pyrogenesis`, this
commit
also mostly removes its source from our code-tree (some headers are
retained for
Windows builds).


If you are a user of...

Linux/BSD: You will now need to have `fmt` installed from your
distribution's
           package repository. The minimum supported version of `fmt` is
`4.0`.

      OSX: The source is acquired and compiled (in `build-osx-libs.sh`),
           then included and linked automatically.

  Windows: The relevant header files are retained and, along with a
pre-built
           library, are the only things still bundled.


Accepted by: wraitii
Tested by:
* Freagarach (Lubuntu 18.04, `fmt 4.0.0`)
* Krinkle (MacOS 10.14, `fmt 6.1.2`)
* nephele (Alpine Linux)
* wraitii (MacOS 10.14)
* Nescio (Fedora 33, `fmt 7.0.3`)

Windows library files built by: Stan
Fixes: #3190
Differential Revision: https://code.wildfiregames.com/D2689
This was SVN commit r24267.
This commit is contained in:
s0600204 2020-11-26 21:01:32 +00:00
parent fb3a0b7add
commit d7d0f142d8
20 changed files with 138 additions and 4095 deletions

View File

@ -63,9 +63,6 @@ in particular, let us know and we can try to clarify it.
/source/scriptinterface/third_party
MPL 2.0
/source/third_party/fmt
BSD
/source/third_party/encryption
GPL version 2 (or later)
ISC (pkcs5_pbkdf2.cpp)

View File

@ -263,6 +263,51 @@ extern_lib_defs = {
end
end,
},
fmt = {
compile_settings = function()
if os.istarget("windows") or os.istarget("macosx") then
add_default_include_paths("fmt")
end
-- With Linux & BSD, we assume that fmt is installed in a standard location.
--
-- It would be nice to not assume, and to instead use pkgconfig: however that
-- requires fmt 5.3.0 or greater.
--
-- Unfortunately (at the time of writing) only 69 out of 95 (~72.6%) of distros
-- that provide a fmt package meet this, according to
-- https://repology.org/badge/vertical-allrepos/fmt.svg?minversion=5.3
--
-- Whilst that might seem like a healthy majority, this does not include the 2018
-- Long Term Support and 2019.10 releases of Ubuntu - not only popular and widely
-- used as-is, but which are also used as a base for other popular distros (e.g.
-- Mint).
--
-- When fmt 5.3 (or better) becomes more widely used, then we can safely use the
-- following line:
-- pkgconfig.add_includes("fmt")
end,
link_settings = function()
if os.istarget("windows") or os.istarget("macosx") then
add_default_lib_paths("fmt")
end
if os.istarget("windows") then
add_default_links({
win_names = { "fmt" },
dbg_suffix = "d",
no_delayload = 1,
})
else
add_default_links({
unix_names = { "fmt" },
})
-- See comment above as to why this is commented out.
-- pkgconfig.add_links("fmt")
end
end
},
gloox = {
compile_settings = function()
if os.istarget("windows") then

View File

@ -594,6 +594,7 @@ function setup_all_libs ()
"spidermonkey",
"enet",
"boost", -- dragged in via server->simulation.h->random
"fmt",
}
if not _OPTIONS["without-miniupnpc"] then
table.insert(extern_libs, "miniupnpc")
@ -605,6 +606,7 @@ function setup_all_libs ()
}
extern_libs = {
"boost", -- dragged in via simulation.h and scriptinterface.h
"fmt",
"spidermonkey",
}
setup_static_lib_project("rlinterface", source_dirs, extern_libs, { no_pch = 1 })
@ -615,6 +617,7 @@ function setup_all_libs ()
extern_libs = {
"iconv",
"boost",
"fmt",
}
setup_third_party_static_lib_project("tinygettext", source_dirs, extern_libs, { } )
@ -648,7 +651,8 @@ function setup_all_libs ()
"icu",
"iconv",
"libsodium",
"tinygettext"
"tinygettext",
"fmt",
}
setup_static_lib_project("lobby", source_dirs, extern_libs, {})
@ -662,6 +666,7 @@ function setup_all_libs ()
extern_libs = {
"boost",
"gloox",
"fmt",
}
if _OPTIONS["build-shared-glooxwrapper"] then
setup_shared_lib_project("glooxwrapper", source_dirs, extern_libs, {})
@ -677,7 +682,8 @@ function setup_all_libs ()
extern_libs = {
"spidermonkey",
"boost",
"libsodium"
"libsodium",
"fmt",
}
setup_static_lib_project("lobby", source_dirs, extern_libs, {})
files { source_root.."lobby/Globals.cpp" }
@ -697,6 +703,7 @@ function setup_all_libs ()
"boost",
"opengl",
"spidermonkey",
"fmt",
}
setup_static_lib_project("simulation2", source_dirs, extern_libs, {})
@ -710,6 +717,7 @@ function setup_all_libs ()
"spidermonkey",
"valgrind",
"sdl",
"fmt",
}
setup_static_lib_project("scriptinterface", source_dirs, extern_libs, {})
@ -728,7 +736,6 @@ function setup_all_libs ()
"maths/scripting",
"i18n",
"i18n/scripting",
"third_party/fmt",
}
extern_libs = {
"spidermonkey",
@ -743,6 +750,7 @@ function setup_all_libs ()
"icu",
"iconv",
"libsodium",
"fmt",
}
if not _OPTIONS["without-audio"] then
@ -765,7 +773,8 @@ function setup_all_libs ()
"opengl",
"sdl", -- key definitions
"spidermonkey", -- for graphics/scripting
"boost"
"boost",
"fmt",
}
if not _OPTIONS["without-nvtt"] then
table.insert(extern_libs, "nvtt")
@ -781,7 +790,8 @@ function setup_all_libs ()
"boost",
"sdl", -- key definitions
"opengl",
"spidermonkey"
"spidermonkey",
"fmt",
}
setup_static_lib_project("atlas", source_dirs, extern_libs, {})
@ -803,6 +813,7 @@ function setup_all_libs ()
"tinygettext",
"icu",
"iconv",
"fmt",
}
if not _OPTIONS["without-audio"] then
table.insert(extern_libs, "openal")
@ -836,6 +847,7 @@ function setup_all_libs ()
"zlib",
"valgrind",
"cxxtest",
"fmt",
}
-- CPU architecture-specific
@ -940,6 +952,7 @@ used_extern_libs = {
"icu",
"iconv",
"libsodium",
"fmt",
"valgrind",
}

View File

@ -32,6 +32,9 @@ win32/ contains headers and precompiled static libs for Windows builds.
win32/enet
MIT
win32/fmt
MIT
win32/gloox
GPL v3

View File

@ -46,6 +46,7 @@ ICU_VERSION="icu4c-67_1"
ENET_VERSION="enet-1.3.17"
MINIUPNPC_VERSION="miniupnpc-2.1"
SODIUM_VERSION="libsodium-1.0.18"
FMT_VERSION="7.1.3"
# --------------------------------------------------------------
# Bundled with the game:
# * SpiderMonkey
@ -892,6 +893,49 @@ else
fi
popd > /dev/null
# --------------------------------------------------------------
echo -e "Building fmt..."
LIB_DIRECTORY="fmt-$FMT_VERSION"
LIB_ARCHIVE="$FMT_VERSION.tar.gz"
LIB_URL="https://github.com/fmtlib/fmt/archive/"
mkdir -p fmt
pushd fmt > /dev/null
if [[ "$force_rebuild" = "true" ]] || [[ ! -e .already-built ]] || [[ "$(<.already-built)" != "$FMT_VERSION" ]]
then
rm -f .already-built
download_lib $LIB_URL $LIB_ARCHIVE
rm -rf $LIB_DIRECTORY include lib
tar -xf $LIB_ARCHIVE
pushd $LIB_DIRECTORY
# It appears that older versions of Clang require constexpr statements to have a user-set constructor.
patch -Np1 -i ../../patches/fmt_constexpr.diff
mkdir -p build
pushd build
(cmake .. \
-DFMT_TEST=False \
-DFMT_DOC=False \
&& make fmt ${JOBS}) || die "fmt build failed"
popd
mkdir -p ../lib
cp build/libfmt.a ../lib/
cp -r include ../include
popd
echo "$FMT_VERSION" > .already-built
else
already_built
fi
popd > /dev/null
# --------------------------------------------------------------------
# The following libraries are shared on different OSes and may
# be customized, so we build and install them from bundled sources

View File

@ -0,0 +1,13 @@
diff --git a/include/fmt/os.h b/include/fmt/os.h
index 88151006..11c3b2cc 100644
--- a/include/fmt/os.h
+++ b/include/fmt/os.h
@@ -375,7 +375,7 @@ struct ostream_params {
};
} // namespace detail
-static constexpr detail::buffer_size buffer_size;
+static constexpr detail::buffer_size buffer_size{};
// A fast output stream which is not thread-safe.
class ostream final : private detail::buffer<char> {

View File

@ -24,6 +24,7 @@
#include "SkeletonAnimDef.h"
#include "maths/MathUtil.h"
#include "maths/Matrix3D.h"
#include "ps/CStr.h"
#include "ps/FileIo.h"

View File

@ -60,8 +60,6 @@ need only be renamed (e.g. _open, _stat).
#ifndef INCLUDED_POSIX
#define INCLUDED_POSIX
#include <cmath> // see isfinite comment below
#if OS_WIN
# include "lib/sysdep/os/win/wposix/wposix.h"
#endif
@ -114,18 +112,4 @@ extern wchar_t* wcsdup(const wchar_t* str);
extern int wcscasecmp(const wchar_t* s1, const wchar_t* s2);
#endif
// Some systems have C99 support but in C++ they provide only std::isfinite
// and not isfinite. C99 specifies that isfinite is a macro, so we can use
// #ifndef and define it if it's not there already.
// We've included <cmath> above to make sure it defines that macro.
#ifndef isfinite
# if MSC_VERSION
# define isfinite _finite
# define isnan _isnan
# else
# define isfinite std::isfinite
# define isnan std::isnan
# endif
#endif
#endif // #ifndef INCLUDED_POSIX

View File

@ -146,7 +146,7 @@ public:
static CFixed FromFloat(float n)
{
if (!isfinite(n))
if (!std::isfinite(n))
return CFixed(0);
float scaled = n * fract_pow2;
return CFixed(round_away_from_zero<T>(scaled));
@ -154,7 +154,7 @@ public:
static CFixed FromDouble(double n)
{
if (!isfinite(n))
if (!std::isfinite(n))
return CFixed(0);
double scaled = n * fract_pow2;
return CFixed(round_away_from_zero<T>(scaled));

View File

@ -25,7 +25,7 @@
#include <set>
#include <sstream>
#include "third_party/fmt/format.h"
#include <fmt/printf.h>
class CLogger;
extern CLogger* g_Logger;

View File

@ -23,6 +23,7 @@
#include "FileIo.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "ps/Filesystem.h"
#include "lib/byte_order.h"

View File

@ -19,6 +19,7 @@
#include "Filesystem.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "ps/Profile.h"
#include "lib/res/h_mgr.h" // h_reload

View File

@ -183,7 +183,7 @@ public:
* clamped to 0.0f.
**/
inline void SetSimRate(float simRate)
{ if (isfinite(simRate)) m_SimRate = std::max(simRate, 0.0f); }
{ if (std::isfinite(simRate)) m_SimRate = std::max(simRate, 0.0f); }
inline float GetSimRate() const
{ return m_SimRate; }

View File

@ -22,6 +22,7 @@
#include "lib/timer.h"
#include "lib/utf8.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "ps/Filesystem.h"
#include <libxml/relaxng.h>

View File

@ -62,8 +62,8 @@
*/
#include "lib/file/vfs/vfs.h"
#include "ps/CStr.h"
class CStr8;
class XMBElement;
class XMBFile;
class XMLWriter_Element;
@ -98,7 +98,7 @@ private:
bool m_PrettyPrint;
CStr8 m_Data;
CStr m_Data;
int m_Indent;
XMLWriter_Element* m_LastElement;
};
@ -119,7 +119,7 @@ private:
friend class XMLWriter_File;
XMLWriter_File* m_File;
CStr8 m_Name;
CStr m_Name;
int m_Type;
};

View File

@ -15,9 +15,9 @@
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lib/self_test.h"
#include <fmt/printf.h>
#include "third_party/fmt/format.h"
#include "lib/self_test.h"
class TestFmt : public CxxTest::TestSuite
{
@ -39,7 +39,7 @@ public:
TS_ASSERT_EQUALS(fmt::sprintf("%f", 0.5f), "0.500000");
TS_ASSERT_EQUALS(fmt::sprintf("%.1f", 0.1111f), "0.1");
TS_ASSERT_EQUALS(fmt::sprintf("%d", 0x100000001ULL), "1");
TS_ASSERT_EQUALS(fmt::sprintf("%d", 0x100000001ULL), "4294967297");
if (sizeof(long) == sizeof(int32_t))
{
TS_ASSERT_EQUALS(fmt::sprintf("%ld", 0x100000001ULL), "1");

View File

@ -21,6 +21,7 @@
#include "ScriptExceptions.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "scriptinterface/ScriptInterface.h"
bool ScriptException::IsPending(const ScriptRequest& rq)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,221 +0,0 @@
--- format.h 2020-02-09 20:52:31.892811631 +0100
+++ 0ad/source/third_party/fmt/format.h 2020-03-04 21:53:39.475417249 +0100
@@ -1,4 +1,9 @@
/*
+ * Slightly modified version of fmt, by Wildfire Games, for 0 A.D.
+ * Based on fmt v1.1.0 from https://github.com/fmtlib/fmt
+ */
+
+/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
@@ -37,10 +42,11 @@
#include <algorithm>
#include <limits>
#include <stdexcept>
-#include <string>
#include <sstream>
-#if _SECURE_SCL
+#include "ps/CStr.h"
+
+#if defined(_SECURE_SCL) && _SECURE_SCL
# include <iterator>
#endif
@@ -129,9 +135,13 @@
// Variadic templates are available in GCC since version 4.4
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
// since version 2013.
+# if defined(_MSC_VER)
+# define FMT_USE_VARIADIC_TEMPLATES 1
+# else
# define FMT_USE_VARIADIC_TEMPLATES \
(FMT_HAS_FEATURE(cxx_variadic_templates) || \
- (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800)
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11))
+# endif
#endif
#ifndef FMT_USE_RVALUE_REFERENCES
@@ -139,10 +149,12 @@
// as the latter doesn't provide std::move.
# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
# define FMT_USE_RVALUE_REFERENCES 0
+# elif defined(_MSC_VER)
+# define FMT_USE_RVALUE_REFERENCES 1
# else
# define FMT_USE_RVALUE_REFERENCES \
(FMT_HAS_FEATURE(cxx_rvalue_references) || \
- (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600)
+ (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11))
# endif
#endif
@@ -151,7 +163,7 @@
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
-#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
+#if (defined(FMT_USE_NOEXCEPT) && FMT_USE_NOEXCEPT) || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11)
# define FMT_NOEXCEPT noexcept
#else
@@ -160,7 +172,7 @@
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
-#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
+#if (defined(FMT_USE_DELETED_FUNCTIONS) && FMT_USE_DELETED_FUNCTIONS) || FMT_HAS_FEATURE(cxx_deleted_functions) || \
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
@@ -287,7 +299,7 @@
// to avoid dynamic memory allocation.
enum { INLINE_BUFFER_SIZE = 500 };
-#if _SECURE_SCL
+#if defined(_SECURE_SCL) && _SECURE_SCL
// Use checked iterator to avoid warnings on MSVC.
template <typename T>
inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
@@ -483,7 +495,7 @@
template <typename Char>
class BasicCharTraits {
public:
-#if _SECURE_SCL
+#if defined(_SECURE_SCL) && _SECURE_SCL
typedef stdext::checked_array_iterator<Char*> CharPtr;
#else
typedef Char *CharPtr;
@@ -869,6 +881,7 @@
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
FMT_MAKE_STR_VALUE(const std::string &, STRING)
FMT_MAKE_STR_VALUE(StringRef, STRING)
+ FMT_MAKE_STR_VALUE(const CStr &, STRING)
#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
@@ -1567,7 +1580,7 @@
typedef typename internal::CharTraits<Char>::CharPtr CharPtr;
-#if _SECURE_SCL
+#if defined(_SECURE_SCL) && _SECURE_SCL
// Returns pointer value.
static Char *get(CharPtr p) { return p.base(); }
#else
@@ -2074,7 +2087,7 @@
Char fill = static_cast<Char>(spec.fill());
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
-#if _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER
// MSVC's vsnprintf_s doesn't work with zero size, so reserve
// space for at least one extra character to make the size non-zero.
// Note that the buffer's capacity will increase by more than 1.
--- format.cpp 2020-02-09 20:52:10.936425878 +0100
+++ 0ad/source/third_party/fmt/format.cpp 2020-03-04 21:36:15.755684084 +0100
@@ -1,4 +1,9 @@
/*
+ * Slightly modified version of fmt, by Wildfire Games, for 0 A.D.
+ * Based on fmt v1.1.0 from https://github.com/fmtlib/fmt
+ */
+
+/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
@@ -24,6 +29,7 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "precompiled.h"
#include "format.h"
@@ -48,7 +54,7 @@
#if __GNUC__ && !__EXCEPTIONS
# define FMT_EXCEPTIONS 0
#endif
-#if _MSC_VER && !_HAS_EXCEPTIONS
+#if defined(_MSC_VER) && _MSC_VER && !_HAS_EXCEPTIONS
# define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
@@ -79,17 +85,17 @@
# define FMT_FUNC
#endif
-#if _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4127) // conditional expression is constant
-# pragma warning(disable: 4702) // unreachable code
-#endif
-
namespace {
#ifndef _MSC_VER
# define FMT_SNPRINTF snprintf
#else // _MSC_VER
+
+# pragma warning(push)
+# pragma warning(disable: 4127) // conditional expression is constant
+# pragma warning(disable: 4702) // unreachable code
+# pragma warning(disable: 4456) // hides previous local declaration
+
inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
va_list args;
va_start(args, format);
@@ -136,24 +142,24 @@
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
assert(buffer != 0 && buffer_size != 0);
int result = 0;
-#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__
+#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || (defined(__ANDROID__) && __ANDROID__)
// XSI-compliant version of strerror_r.
result = strerror_r(error_code, buffer, buffer_size);
if (result != 0)
result = errno;
-#elif _GNU_SOURCE
+#elif defined(_GNU_SOURCE) && !defined(__BIONIC__)
// GNU-specific version of strerror_r.
char *message = strerror_r(error_code, buffer, buffer_size);
// If the buffer is full then the message is probably truncated.
if (message == buffer && strlen(buffer) == buffer_size - 1)
result = ERANGE;
buffer = message;
-#elif __MINGW32__
+#elif defined(__MINGW32__)
errno = 0;
(void)buffer_size;
buffer = strerror(error_code);
result = errno;
-#elif _WIN32
+#elif defined(_WIN32)
result = strerror_s(buffer, buffer_size, error_code);
// If the buffer is full then the message is probably truncated.
if (result == 0 && std::strlen(buffer) == buffer_size - 1)
@@ -627,8 +633,11 @@
const StrChar *str_value = s.value;
std::size_t str_size = s.size;
if (str_size == 0) {
- if (!str_value)
- FMT_THROW(FormatError("string pointer is null"));
+ if (!str_value) {
+ Char err[] = { '(', 'n', 'u', 'l', 'l', ')' };
+ write_str(err, sizeof(err)/sizeof(Char), spec);
+ return;
+ }
if (*str_value)
str_size = std::char_traits<StrChar>::length(str_value);
}
@@ -1164,6 +1173,6 @@
#endif // FMT_HEADER_ONLY
-#if _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER
# pragma warning(pop)
#endif