mirror of
https://github.com/anope/anope.git
synced 2026-06-12 19:14:47 +02:00
Make module version system work
This commit is contained in:
@@ -7,7 +7,7 @@ get_target_property(version_BINARY version LOCATION)
|
||||
# Modify version.h from the above executable, with dependencies to version.cpp
|
||||
# and all of the source files in the main build
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_build
|
||||
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h
|
||||
DEPENDS version ${SRC_SRCS}
|
||||
)
|
||||
# Add version to list of files for CPack to ignore
|
||||
@@ -15,6 +15,7 @@ get_filename_component(version_BINARY ${version_BINARY} NAME)
|
||||
add_to_cpack_ignored_files("${version_BINARY}$" TRUE)
|
||||
if(NOT WIN32)
|
||||
add_to_cpack_ignored_files("version.h$" TRUE)
|
||||
add_to_cpack_ignored_files("build.h$" TRUE)
|
||||
endif(NOT WIN32)
|
||||
|
||||
set(PCH_SOURCES_GCH "")
|
||||
|
||||
+14
-6
@@ -20,6 +20,7 @@
|
||||
#include "timers.h"
|
||||
#include "logger.h"
|
||||
#include "extensible.h"
|
||||
#include "version.h"
|
||||
|
||||
/** This definition is used as shorthand for the various classes
|
||||
* and functions needed to make a module loadable by the OS.
|
||||
@@ -40,6 +41,10 @@
|
||||
extern "C" void AnopeFini(x *m) \
|
||||
{ \
|
||||
delete m; \
|
||||
} \
|
||||
extern "C" DllExport ModuleVersion AnopeVersion() \
|
||||
{ \
|
||||
return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); \
|
||||
}
|
||||
#else
|
||||
# define MODULE_INIT(x) \
|
||||
@@ -50,6 +55,10 @@
|
||||
extern "C" DllExport void AnopeFini(x *m) \
|
||||
{ \
|
||||
delete m; \
|
||||
} \
|
||||
extern "C" DllExport ModuleVersion AnopeVersion() \
|
||||
{ \
|
||||
return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -279,12 +288,6 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
void SetAuthor(const Anope::string &author);
|
||||
|
||||
/** Get the version of Anope this module was
|
||||
* compiled against
|
||||
* @return The version
|
||||
*/
|
||||
ModuleVersion GetVersion() const;
|
||||
|
||||
virtual void Prioritize();
|
||||
|
||||
/* Everything below here are events. Modules must ModuleManager::Attach to these events
|
||||
@@ -1206,6 +1209,11 @@ class CoreExport ModuleManager
|
||||
* @return MOD_ERR_OK on success, anything else on fail
|
||||
*/
|
||||
static ModuleReturn DeleteModule(Module *m);
|
||||
|
||||
/** Get the version of Anope the module was compiled against
|
||||
* @return The version
|
||||
*/
|
||||
static ModuleVersion GetVersion(void *handle);
|
||||
};
|
||||
|
||||
#endif // MODULES_H
|
||||
|
||||
+88
-35
@@ -13,7 +13,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
static std::string get_git_hash(const std::string &git_dir)
|
||||
{
|
||||
@@ -45,29 +45,16 @@ static std::string get_git_hash(const std::string &git_dir)
|
||||
return "g" + filebuf.substr(0, 7);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cerr << "Syntax: " << argv[0] << " <base> <version.h>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
|
||||
std::string git_dir = std::string(argv[1]) + "/.git";
|
||||
|
||||
std::fstream fd;
|
||||
|
||||
fd.clear();
|
||||
fd.open(version_sh.c_str(), std::ios::in);
|
||||
std::fstream fd(version_sh.c_str(), std::ios::in);
|
||||
if (!fd.is_open())
|
||||
{
|
||||
std::cerr << "Error: Unable to open src/version.sh for reading: " << version_sh << std::endl;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string filebuf;
|
||||
std::list<std::pair<std::string, std::string> > versions;
|
||||
while (getline(fd, filebuf))
|
||||
{
|
||||
if (!filebuf.find("VERSION_"))
|
||||
@@ -75,24 +62,25 @@ int main(int argc, char *argv[])
|
||||
size_t eq = filebuf.find('=');
|
||||
|
||||
std::string type = filebuf.substr(0, eq);
|
||||
std::string value = filebuf.substr(eq + 2, filebuf.length() - eq - 3);
|
||||
versions.push_back(std::make_pair(type, value));
|
||||
std::string value = filebuf.substr(eq + 1);
|
||||
|
||||
versions[type] = value;
|
||||
}
|
||||
}
|
||||
|
||||
fd.close();
|
||||
|
||||
std::string git_version = get_git_hash(git_dir);
|
||||
if (!git_version.empty())
|
||||
versions.push_back(std::make_pair("VERSION_GIT", git_version));
|
||||
return true;
|
||||
}
|
||||
|
||||
fd.clear();
|
||||
fd.open(argv[2], std::ios::in);
|
||||
static bool write_build_h(const std::string &buildh)
|
||||
{
|
||||
std::fstream fd(buildh.c_str(), std::ios::in);
|
||||
|
||||
std::string build = "#define BUILD 1";
|
||||
if (fd.is_open())
|
||||
{
|
||||
while (getline(fd, filebuf))
|
||||
for (std::string filebuf; getline(fd, filebuf);)
|
||||
{
|
||||
if (!filebuf.find("#define BUILD"))
|
||||
{
|
||||
@@ -110,27 +98,92 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
fd.clear();
|
||||
fd.open(argv[2], std::ios::out);
|
||||
|
||||
fd.open(buildh.c_str(), std::ios::out);
|
||||
if (!fd.is_open())
|
||||
{
|
||||
std::cerr << "Error: Unable to include/version.h for writing: " << argv[2] << std::endl;
|
||||
return 1;
|
||||
std::cerr << "Error: Unable to open build.h for writing: " << buildh << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl;
|
||||
fd << build << std::endl;
|
||||
fd.close();
|
||||
|
||||
for (std::list<std::pair<std::string, std::string> >::iterator it = versions.begin(), it_end = versions.end(); it != it_end; ++it)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_version_h(const std::string &versionh, std::map<std::string, std::string> &versions)
|
||||
{
|
||||
std::fstream fd(versionh.c_str(), std::ios::in);
|
||||
|
||||
if (!fd.is_open())
|
||||
return;
|
||||
|
||||
for (std::string filebuf; getline(fd, filebuf);)
|
||||
{
|
||||
if (it->first == "VERSION_EXTRA" || it->first == "VERSION_GIT")
|
||||
fd << "#define " << it->first << " \"" << it->second << "\"" << std::endl;
|
||||
else
|
||||
fd << "#define " << it->first << " " << it->second << std::endl;
|
||||
if (!filebuf.find("#define VERSION_"))
|
||||
{
|
||||
size_t space = filebuf.substr(8).find(' ');
|
||||
|
||||
std::string name = filebuf.substr(8).substr(0, space),
|
||||
version = filebuf.substr(8).substr(space + 1);
|
||||
|
||||
versions[name] = version;
|
||||
}
|
||||
}
|
||||
|
||||
fd << build << std::endl;
|
||||
fd.close();
|
||||
}
|
||||
|
||||
static bool write_version_h(const std::string &versionh, const std::map<std::string, std::string> &versions)
|
||||
{
|
||||
std::fstream fd(versionh.c_str(), std::ios::out);
|
||||
|
||||
if (!fd.is_open())
|
||||
return false;
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = versions.begin(); it != versions.end(); ++it)
|
||||
{
|
||||
fd << "#define " << it->first << " " << it->second << std::endl;
|
||||
}
|
||||
|
||||
fd.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4)
|
||||
{
|
||||
std::cerr << "Syntax: " << argv[0] << " <base> <version.h> <build.h>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
|
||||
std::string git_dir = std::string(argv[1]) + "/.git";
|
||||
std::string versionh = argv[2];
|
||||
std::string buildh = argv[3];
|
||||
|
||||
std::map<std::string, std::string> versions, old_versions;
|
||||
|
||||
if (!read_version_sh(version_sh, versions))
|
||||
return -1;
|
||||
|
||||
std::string git_version = get_git_hash(git_dir);
|
||||
if (!git_version.empty())
|
||||
versions["VERSION_GIT"] = '"' + git_version + '"';
|
||||
|
||||
if (!write_build_h(buildh))
|
||||
return -1;
|
||||
|
||||
read_version_h(versionh, old_versions);
|
||||
|
||||
if (versions == old_versions)
|
||||
return 0;
|
||||
|
||||
if (!write_version_h(versionh, versions))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-6
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "version.h"
|
||||
#include "build.h"
|
||||
#include "modules.h"
|
||||
#include "lists.h"
|
||||
#include "config.h"
|
||||
@@ -617,11 +617,6 @@ const Anope::string Anope::LastError()
|
||||
#endif
|
||||
}
|
||||
|
||||
ModuleVersion Module::GetVersion() const
|
||||
{
|
||||
return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
|
||||
}
|
||||
|
||||
Anope::string Anope::Version()
|
||||
{
|
||||
#ifdef VERSION_GIT
|
||||
|
||||
+58
-28
@@ -166,6 +166,46 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
|
||||
return MOD_ERR_NOLOAD;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ModuleVersion v = GetVersion(handle);
|
||||
|
||||
if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor()))
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort();
|
||||
dlclose(handle);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetMajor() > Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() > Anope::VersionMinor()))
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort();
|
||||
dlclose(handle);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetPatch() < Anope::VersionPatch())
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against an older version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
|
||||
dlclose(handle);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetPatch() > Anope::VersionPatch())
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against a newer version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
|
||||
dlclose(handle);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_DEBUG_2) << "Module " << modname << " is compiled against current version of Anope " << Anope::VersionShort();
|
||||
}
|
||||
}
|
||||
catch (const ModuleException &ex)
|
||||
{
|
||||
/* this error has already been logged */
|
||||
dlclose(handle);
|
||||
return MOD_ERR_NOLOAD;
|
||||
}
|
||||
|
||||
dlerror();
|
||||
Module *(*func)(const Anope::string &, const Anope::string &) = function_cast<Module *(*)(const Anope::string &, const Anope::string &)>(dlsym(handle, "AnopeInit"));
|
||||
err = dlerror();
|
||||
@@ -206,34 +246,6 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
|
||||
m->filename = pbuf;
|
||||
m->handle = handle;
|
||||
|
||||
ModuleVersion v = m->GetVersion();
|
||||
if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor()))
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort();
|
||||
DeleteModule(m);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetMajor() > Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() > Anope::VersionMinor()))
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort();
|
||||
DeleteModule(m);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetPatch() < Anope::VersionPatch())
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against an older version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
|
||||
DeleteModule(m);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else if (v.GetPatch() > Anope::VersionPatch())
|
||||
{
|
||||
Log() << "Module " << modname << " is compiled against a newer version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
|
||||
DeleteModule(m);
|
||||
return MOD_ERR_VERSION;
|
||||
}
|
||||
else
|
||||
Log(LOG_DEBUG_2) << "Module " << modname << " is compiled against current version of Anope " << Anope::VersionShort();
|
||||
|
||||
/* Initialize config */
|
||||
try
|
||||
{
|
||||
@@ -272,6 +284,24 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
|
||||
return MOD_ERR_OK;
|
||||
}
|
||||
|
||||
ModuleVersion ModuleManager::GetVersion(void *handle)
|
||||
{
|
||||
dlerror();
|
||||
ModuleVersion (*func)() = function_cast<ModuleVersion (*)()>(dlsym(handle, "AnopeVersion"));;
|
||||
if (!func)
|
||||
{
|
||||
Log() << "No version function found, not an Anope module";
|
||||
|
||||
const char *err = dlerror();
|
||||
if (err && *err)
|
||||
Log(LOG_DEBUG) << err;
|
||||
|
||||
throw ModuleException("No version");
|
||||
}
|
||||
|
||||
return func();
|
||||
}
|
||||
|
||||
ModuleReturn ModuleManager::UnloadModule(Module *m, User *u)
|
||||
{
|
||||
if (!m)
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
VERSION_MAJOR="2"
|
||||
VERSION_MINOR="0"
|
||||
VERSION_PATCH="2"
|
||||
VERSION_MAJOR=2
|
||||
VERSION_MINOR=0
|
||||
VERSION_PATCH=2
|
||||
VERSION_EXTRA="-git"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user