modernize-cmake-1
Fiftytwo 2020-04-07 19:10:32 +02:00
commit 9db6bb63e4
16 changed files with 155 additions and 27 deletions

View File

@ -198,7 +198,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_definitions(-DNOEXCEPT= -DHAS_MSVC_EXCEPTION_BUG)
# Needed for Debug information (it's set to "No" by default for some reason)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /NODEFAULTLIB:MSVCRTD /NODEFAULTLIB:LIBCMT")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
else()
message(FATAL_ERROR "Your C++ compiler doesn't seem to be supported.")
@ -230,7 +230,10 @@ option(DEV_BUILD "Enable development build (enables some debugging tools, local
# PLEASE DO NOT USE ON UNOFFICIAL BUILDS. Thanks.
option(OFFICIAL_COLOBOT_BUILD "Official build (changes crash screen text)" OFF)
# Portable build - load all data from current directory
# Hardcode relative paths instead of absolute paths
option(USE_RELATIVE_PATHS "Generate relative paths from absolute paths" OFF)
# Portable build - load all data from the base directory
option(PORTABLE "Portable build" OFF)
# Portable saves - suitable for e.g. putting the whole game on external storage and moving your saves with it
@ -391,12 +394,12 @@ endif()
# Installation paths defined before compiling sources
if(PORTABLE OR (PLATFORM_WINDOWS AND MXE))
# We need to use STRING because PATH doesn't accept relative paths
set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
set(USE_RELATIVE_PATHS ON)
elseif(PLATFORM_WINDOWS)
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
@ -417,6 +420,18 @@ else()
set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/share/doc/colobot CACHE PATH "Colobot documentation directory")
endif()
# Generate relative paths from absolute paths
if(USE_RELATIVE_PATHS)
message(STATUS "Generating relative paths")
file(RELATIVE_PATH COLOBOT_DATA_DIR ${COLOBOT_INSTALL_BIN_DIR} ${COLOBOT_INSTALL_DATA_DIR})
file(RELATIVE_PATH COLOBOT_I18N_DIR ${COLOBOT_INSTALL_BIN_DIR} ${COLOBOT_INSTALL_I18N_DIR})
add_definitions(-DUSE_RELATIVE_PATHS)
else()
set(COLOBOT_DATA_DIR ${COLOBOT_INSTALL_DATA_DIR})
set(COLOBOT_I18N_DIR ${COLOBOT_INSTALL_I18N_DIR})
endif()
# Subdirectory with sources
add_subdirectory(src)

2
Jenkinsfile vendored
View File

@ -27,6 +27,7 @@ pipeline {
dir('build/windows') {
sh '''
# FIXME: without -lsetupapi linking sdl2 fails
rm -rf *
/opt/mxe/usr/bin/i686-w64-mingw32.static-cmake \
-DCMAKE_CXX_STANDARD_LIBRARIES="-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lsetupapi" \
-DCMAKE_INSTALL_PREFIX=/install \
@ -53,6 +54,7 @@ pipeline {
sh 'mkdir -p build/linux'
dir('build/linux') {
sh '''
rm -rf *
cmake \
-DCMAKE_INSTALL_PREFIX=/install -DCMAKE_SKIP_INSTALL_RPATH=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=1 ../..

View File

@ -65,6 +65,8 @@ elseif(PLATFORM_WINDOWS)
find_library(TIFF_LIBRARY NAMES tiff.lib)
find_library(LZMA_LIBRARY NAMES lzma.lib)
find_library(FREETYPE_LIBRARY NAMES freetype.lib)
find_library(ICONV_LIBRARY NAMES libiconv.lib)
find_library(CHARSET_LIBRARY NAMES libcharset.lib)
set(MSVC_LIBS
${LIBINTL_LIBRARY}
${OPENAL_MSVC_LIBS}
@ -73,6 +75,8 @@ elseif(PLATFORM_WINDOWS)
${BZ2_LIBRARY}
${LZMA_LIBRARY}
${FREETYPE_LIBRARY}
${ICONV_LIBRARY}
${CHARSET_LIBRARY}
winmm.lib
dxguid.lib
imm32.lib
@ -81,6 +85,7 @@ elseif(PLATFORM_WINDOWS)
version.lib
wsock32.lib
ws2_32.lib
setupapi.lib
)
else(${MSVC_STATIC})
set(MSVC_LIBS ${LIBINTL_LIBRARY})

View File

@ -220,6 +220,30 @@ CSoundInterface* CApplication::GetSound()
return m_sound.get();
}
void CApplication::LoadEnvironmentVariables()
{
auto dataDir = m_systemUtils->GetEnvVar("COLOBOT_DATA_DIR");
if (!dataDir.empty())
{
m_pathManager->SetDataPath(dataDir);
GetLogger()->Info("Using data dir (based on environment variable): '%s'\n", dataDir.c_str());
}
auto langDir = m_systemUtils->GetEnvVar("COLOBOT_LANG_DIR");
if (!langDir.empty())
{
m_pathManager->SetLangPath(langDir);
GetLogger()->Info("Using lang dir (based on environment variable): '%s'\n", langDir.c_str());
}
auto saveDir = m_systemUtils->GetEnvVar("COLOBOT_SAVE_DIR");
if (!saveDir.empty())
{
m_pathManager->SetSavePath(saveDir);
GetLogger()->Info("Using save dir (based on environment variable): '%s'\n", saveDir.c_str());
}
}
ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
{
enum OptionType
@ -286,15 +310,18 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
GetLogger()->Message("\n");
GetLogger()->Message("%s\n", COLOBOT_FULLNAME);
GetLogger()->Message("\n");
GetLogger()->Message("List of available options:\n");
GetLogger()->Message("List of available options and environment variables:\n");
GetLogger()->Message(" -help this help\n");
GetLogger()->Message(" -debug modes enable debug modes (more info printed in logs; see code for reference of modes)\n");
GetLogger()->Message(" -runscene sceneNNN run given scene on start\n");
GetLogger()->Message(" -scenetest win every mission right after it's loaded\n");
GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
GetLogger()->Message(" -langdir path set custom language directory path\n");
GetLogger()->Message(" environment variable: COLOBOT_LANG_DIR\n");
GetLogger()->Message(" -datadir path set custom data directory path\n");
GetLogger()->Message(" environment variable: COLOBOT_DATA_DIR\n");
GetLogger()->Message(" -savedir path set custom save directory path (must be writable)\n");
GetLogger()->Message(" environment variable: COLOBOT_SAVE_DIR\n");
GetLogger()->Message(" -mod path load datadir mod from given path\n");
GetLogger()->Message(" -resolution WxH set resolution\n");
GetLogger()->Message(" -headless headless mode - disables graphics, sound and user interaction\n");

View File

@ -164,7 +164,9 @@ public:
CSoundInterface* GetSound();
public:
//! Parses commandline arguments
//! Loads some data from environment variables
void LoadEnvironmentVariables();
//! Parses commandline arguments (they take priority)
ParseArgsStatus ParseArguments(int argc, char *argv[]);
//! Initializes the application
bool Create();

View File

@ -172,6 +172,8 @@ int main(int argc, char *argv[])
int code = 0;
CApplication app(systemUtils.get()); // single instance of the application
app.LoadEnvironmentVariables();
ParseArgsStatus status = app.ParseArguments(argc, argv);
if (status == PARSE_ARGS_FAIL)
{

View File

@ -41,7 +41,7 @@ CPathManager::CPathManager(CSystemUtils* systemUtils)
: m_dataPath(systemUtils->GetDataPath())
, m_langPath(systemUtils->GetLangPath())
, m_savePath(systemUtils->GetSaveDir())
, m_modAutoloadDir{ m_dataPath + "/mods", m_savePath + "/mods" }
, m_modAutoloadDir{}
, m_mods{}
{
}
@ -130,6 +130,10 @@ void CPathManager::InitPaths()
{
GetLogger()->Info("Data path: %s\n", m_dataPath.c_str());
GetLogger()->Info("Save path: %s\n", m_savePath.c_str());
m_modAutoloadDir.push_back(m_dataPath + "/mods");
m_modAutoloadDir.push_back(m_savePath + "/mods");
if (!m_modAutoloadDir.empty())
{
GetLogger()->Info("Mod autoload dirs:\n");

View File

@ -18,5 +18,5 @@
#cmakedefine PORTABLE_SAVES @PORTABLE_SAVES@
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@"
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_I18N_DIR@"

View File

@ -36,6 +36,7 @@
#include <iostream>
#include <algorithm>
#include <SDL2/SDL.h>
std::unique_ptr<CSystemUtils> CSystemUtils::Create()
{
@ -176,17 +177,41 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *afte
return result;
}
std::string CSystemUtils::GetBasePath()
{
if (m_basePath.empty())
{
auto* path = SDL_GetBasePath();
m_basePath = path;
SDL_free(path);
}
return m_basePath;
}
std::string CSystemUtils::GetDataPath()
{
#ifdef USE_RELATIVE_PATHS
return GetBasePath() + COLOBOT_DEFAULT_DATADIR;
#else
return COLOBOT_DEFAULT_DATADIR;
#endif
}
std::string CSystemUtils::GetLangPath()
{
#ifdef USE_RELATIVE_PATHS
return GetBasePath() + COLOBOT_I18N_DIR;
#else
return COLOBOT_I18N_DIR;
#endif
}
std::string CSystemUtils::GetSaveDir()
{
return "./saves";
return GetBasePath() + "saves";
}
std::string CSystemUtils::GetEnvVar(const std::string& name)
{
return "";
}

View File

@ -127,6 +127,9 @@ public:
/** The difference is \a after - \a before. */
virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) = 0;
//! Returns the path where the executable binary is located (ends with the path separator)
virtual std::string GetBasePath();
//! Returns the data path (containing textures, levels, helpfiles, etc)
virtual std::string GetDataPath();
@ -136,9 +139,13 @@ public:
//! Returns the save dir location
virtual std::string GetSaveDir();
//! Returns the environment variable with the given name or an empty string if it does not exist
virtual std::string GetEnvVar(const std::string &name);
//! Sleep for given amount of microseconds
virtual void Usleep(int usecs) = 0;
private:
std::string m_basePath;
std::vector<std::unique_ptr<SystemTimeStamp>> m_timeStamps;
};

View File

@ -102,23 +102,23 @@ std::string CSystemUtilsLinux::GetSaveDir()
std::string savegameDir;
// Determine savegame dir according to XDG Base Directory Specification
char *envXDG_DATA_HOME = getenv("XDG_DATA_HOME");
if (envXDG_DATA_HOME == nullptr)
auto envXDG_DATA_HOME = GetEnvVar("XDG_DATA_HOME");
if (envXDG_DATA_HOME.empty())
{
char *envHOME = getenv("HOME");
if (envHOME == nullptr)
auto envHOME = GetEnvVar("HOME");
if (envHOME.empty())
{
GetLogger()->Warn("Unable to find directory for saves - using current directory");
savegameDir = "./saves";
GetLogger()->Warn("Unable to find directory for saves - using default directory");
savegameDir = CSystemUtils::GetSaveDir();
}
else
{
savegameDir = std::string(envHOME) + "/.local/share/colobot";
savegameDir = envHOME + "/.local/share/colobot";
}
}
else
{
savegameDir = std::string(envXDG_DATA_HOME) + "/colobot";
savegameDir = envXDG_DATA_HOME + "/colobot";
}
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
@ -126,6 +126,17 @@ std::string CSystemUtilsLinux::GetSaveDir()
#endif
}
std::string CSystemUtilsLinux::GetEnvVar(const std::string& name)
{
char* envVar = getenv(name.c_str());
if (envVar != nullptr)
{
GetLogger()->Trace("Detected environment variable %s = %s\n", name.c_str(), envVar);
return std::string(envVar);
}
return "";
}
void CSystemUtilsLinux::Usleep(int usec)
{
usleep(usec);

View File

@ -45,6 +45,8 @@ public:
std::string GetSaveDir() override;
std::string GetEnvVar(const std::string& name) override;
void Usleep(int usec) override;
private:

View File

@ -113,6 +113,12 @@ std::string CSystemUtilsMacOSX::GetSaveDir()
#endif
}
std::string CSystemUtilsMacOSX::GetEnvVar(const std::string& str)
{
// TODO: I have no Mac
return std::string();
}
void CSystemUtilsMacOSX::Usleep(int usec)
{
usleep(usec);

View File

@ -36,6 +36,8 @@ public:
std::string GetLangPath() override;
std::string GetSaveDir() override;
std::string GetEnvVar(const std::string& name) override;
void Usleep(int usec) override;
private:

View File

@ -115,15 +115,15 @@ std::string CSystemUtilsWindows::GetSaveDir()
#else
std::string savegameDir;
wchar_t* envUSERPROFILE = _wgetenv(L"USERPROFILE");
if (envUSERPROFILE == nullptr)
auto envUSERPROFILE = GetEnvVar("USERPROFILE");
if (envUSERPROFILE.empty())
{
GetLogger()->Warn("Unable to find directory for saves - using current directory");
savegameDir = "./saves";
GetLogger()->Warn("Unable to find directory for saves - using default directory");
savegameDir = CSystemUtils::GetSaveDir();
}
else
{
savegameDir = UTF8_Encode(std::wstring(envUSERPROFILE)) + "\\colobot";
savegameDir = envUSERPROFILE + "\\colobot";
}
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
@ -131,6 +131,22 @@ std::string CSystemUtilsWindows::GetSaveDir()
#endif
}
std::string CSystemUtilsWindows::GetEnvVar(const std::string& name)
{
std::wstring wname(name.begin(), name.end());
wchar_t* envVar = _wgetenv(wname.c_str());
if (envVar == nullptr)
{
return "";
}
else
{
std::string var = UTF8_Encode(std::wstring(envVar));
GetLogger()->Trace("Detected environment variable %s = %s\n", name.c_str(), var.c_str());
return var;
}
}
void CSystemUtilsWindows::Usleep(int usec)
{
LARGE_INTEGER ft;

View File

@ -43,6 +43,8 @@ public:
std::string GetSaveDir() override;
std::string GetEnvVar(const std::string& name) override;
void Usleep(int usec) override;
public: