Initial commit
This commit is contained in:
459
devtools/create_project/cmake.cpp
Normal file
459
devtools/create_project/cmake.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
CMakeProvider::CMakeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors)
|
||||
: ProjectProvider(global_warnings, project_warnings, global_errors) {
|
||||
}
|
||||
|
||||
const CMakeProvider::Library *CMakeProvider::getLibraryFromFeature(const char *feature, SDLVersion useSDL) const {
|
||||
static const Library s_libraries[] = {
|
||||
{ "sdl", "sdl", kSDLVersion1, "FindSDL", "SDL", "SDL_INCLUDE_DIR", "SDL_LIBRARY", nullptr, nullptr },
|
||||
{ "sdl", "sdl2", kSDLVersion2, nullptr, "SDL2", nullptr, "SDL2_LIBRARIES", nullptr, nullptr },
|
||||
{ "sdl", "sdl3", kSDLVersion3, nullptr, "SDL3", nullptr, "SDL3_LIBRARIES", nullptr, nullptr },
|
||||
{ "freetype2", "freetype2", kSDLVersionAny, "FindFreetype", "Freetype", "FREETYPE_INCLUDE_DIRS", "FREETYPE_LIBRARIES", nullptr, nullptr },
|
||||
{ "zlib", "zlib", kSDLVersionAny, "FindZLIB", "ZLIB", "ZLIB_INCLUDE_DIRS", "ZLIB_LIBRARIES", nullptr, nullptr },
|
||||
{ "png", "libpng", kSDLVersionAny, "FindPNG", "PNG", "PNG_INCLUDE_DIRS", "PNG_LIBRARIES", nullptr, nullptr },
|
||||
{ "jpeg", "libjpeg", kSDLVersionAny, "FindJPEG", "JPEG", "JPEG_INCLUDE_DIRS", "JPEG_LIBRARIES", nullptr, nullptr },
|
||||
{ "mpeg2", "libmpeg2", kSDLVersionAny, "FindMPEG2", "MPEG2", "MPEG2_INCLUDE_DIRS", "MPEG2_mpeg2_LIBRARY", nullptr, nullptr },
|
||||
{ "opengl", nullptr, kSDLVersionAny, "FindOpenGL", "OpenGL", "OPENGL_INCLUDE_DIR", "OPENGL_gl_LIBRARY", nullptr, nullptr },
|
||||
{ "libcurl", "libcurl", kSDLVersionAny, "FindCURL", "CURL", "CURL_INCLUDE_DIRS", "CURL_LIBRARIES", nullptr, "ws2_32" },
|
||||
{ "sdlnet", nullptr, kSDLVersion1, "FindSDL_net", "SDL_net", "SDL_NET_INCLUDE_DIRS", "SDL_NET_LIBRARIES", nullptr, nullptr },
|
||||
LibraryProps("sdlnet", "SDL2_net", kSDLVersion2).Libraries("SDL2_net"),
|
||||
LibraryProps("sdlnet", "SDL3_net", kSDLVersion3).Libraries("SDL3_net"),
|
||||
LibraryProps("flac", "flac").Libraries("FLAC"),
|
||||
LibraryProps("mad", "mad").Libraries("mad"),
|
||||
LibraryProps("mikmod", "mikmod").Libraries("mikmod"),
|
||||
LibraryProps("openmpt", "openmpt").Libraries("openmpt"),
|
||||
LibraryProps("ogg", "ogg").Libraries("ogg"),
|
||||
LibraryProps("vorbis", "vorbisfile vorbis").Libraries("vorbisfile vorbis"),
|
||||
LibraryProps("tremor", "vorbisidec").Libraries("vorbisidec"),
|
||||
LibraryProps("theoradec", "theoradec").Libraries("theoradec"),
|
||||
LibraryProps("vpx", "vpx").Libraries("vpx"),
|
||||
LibraryProps("fluidsynth", "fluidsynth").Libraries("fluidsynth"),
|
||||
LibraryProps("faad", "faad2").Libraries("faad"),
|
||||
LibraryProps("fribidi", "fribidi").Libraries("fribidi"),
|
||||
LibraryProps("discord", "discord").Libraries("discord-rpc"),
|
||||
LibraryProps("tts").WinLibraries("sapi ole32"),
|
||||
LibraryProps("enet").WinLibraries("winmm ws2_32"),
|
||||
LibraryProps("retrowave", "retrowave").Libraries("retrowave"),
|
||||
LibraryProps("a52", "a52").Libraries("a52"),
|
||||
LibraryProps("mpc", "mpcdec").Libraries("mpcdec")
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(s_libraries) / sizeof(s_libraries[0]); i++) {
|
||||
bool matchingSDL = (s_libraries[i].sdlVersion == kSDLVersionAny)
|
||||
|| (s_libraries[i].sdlVersion == useSDL);
|
||||
if (std::strcmp(feature, s_libraries[i].feature) == 0 && matchingSDL) {
|
||||
return &s_libraries[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CMakeProvider::createWorkspace(const BuildSetup &setup) {
|
||||
std::string filename = setup.outputDir + "/CMakeLists.txt";
|
||||
std::ofstream workspace(filename.c_str());
|
||||
if (!workspace || !workspace.is_open())
|
||||
error("Could not open \"" + filename + "\" for writing");
|
||||
|
||||
workspace << "cmake_minimum_required(VERSION 3.13)\n";
|
||||
workspace << "project(" << setup.projectDescription << ")\n\n";
|
||||
|
||||
workspace << R"EOS(set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_CXX_STANDARD 11) # Globally enable C++11
|
||||
add_compile_definitions($<$<NOT:$<CONFIG:Debug>>:RELEASE_BUILD>)
|
||||
add_compile_options($<$<NOT:$<CONFIG:Debug>>:-UNDEBUG>)
|
||||
|
||||
# Remove /D NDEBUG to avoid MSVC warnings about conflicting defines.
|
||||
foreach (flags_var_to_scrub
|
||||
CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_C_FLAGS_MINSIZEREL)
|
||||
string (REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " "
|
||||
"${flags_var_to_scrub}" "${${flags_var_to_scrub}}")
|
||||
endforeach()
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
set(SCUMMVM_LIBS)
|
||||
|
||||
macro(find_feature)
|
||||
set(_OPTIONS_ARGS)
|
||||
set(_ONE_VALUE_ARGS name findpackage_name include_dirs_var libraries_var)
|
||||
set(_MULTI_VALUE_ARGS pkgconfig_name libraries win_libraries)
|
||||
cmake_parse_arguments(_feature "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
|
||||
|
||||
if (_feature_pkgconfig_name AND PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(${_feature_name} REQUIRED ${_feature_pkgconfig_name})
|
||||
include_directories(${${_feature_name}_INCLUDE_DIRS})
|
||||
list(APPEND SCUMMVM_LIBS ${${_feature_name}_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (NOT ${_feature_name}_FOUND)
|
||||
if (_feature_findpackage_name)
|
||||
find_package(${_feature_findpackage_name} REQUIRED)
|
||||
endif()
|
||||
if (_feature_include_dirs_var)
|
||||
include_directories(${${_feature_include_dirs_var}} REQUIRED)
|
||||
endif()
|
||||
if (_feature_libraries_var)
|
||||
list(APPEND SCUMMVM_LIBS ${${_feature_libraries_var}})
|
||||
endif()
|
||||
if (_feature_libraries)
|
||||
list(APPEND SCUMMVM_LIBS ${_feature_libraries})
|
||||
endif()
|
||||
if (WIN32 AND _feature_win_libraries)
|
||||
list(APPEND SCUMMVM_LIBS ${_feature_win_libraries})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
)EOS";
|
||||
|
||||
workspace << R"EOS(function(add_engine engine_name)
|
||||
string(TOUPPER ${engine_name} _engine_var)
|
||||
set(_enable_engine_var "ENABLE_${_engine_var}")
|
||||
if(NOT ${_enable_engine_var})
|
||||
return()
|
||||
endif()
|
||||
add_library(${engine_name} ${ARGN})
|
||||
|
||||
# Generate definitions for the engine
|
||||
add_definitions(-D${_enable_engine_var})
|
||||
foreach(SUB_ENGINE IN LISTS SUB_ENGINES_${_engine_var})
|
||||
add_definitions(-DENABLE_${SUB_ENGINE})
|
||||
endforeach(SUB_ENGINE)
|
||||
file(APPEND "engines/plugins_table.h" "#if PLUGIN_ENABLED_STATIC(${_engine_var})\n")
|
||||
file(APPEND "engines/plugins_table.h" "LINK_PLUGIN(${_engine_var})\n")
|
||||
file(APPEND "engines/plugins_table.h" "#endif\n")
|
||||
|
||||
# Enable C++11
|
||||
set_property(TARGET ${engine_name} PROPERTY CXX_STANDARD 11)
|
||||
set_property(TARGET ${engine_name} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Link against the engine
|
||||
target_link_libraries()EOS" << setup.projectName << R"( ${engine_name})
|
||||
endfunction()
|
||||
|
||||
)";
|
||||
|
||||
workspace << "# Define the engines and subengines\n";
|
||||
writeEngines(setup, workspace);
|
||||
writeSubEngines(setup, workspace);
|
||||
workspace << "# Generate options for the engines\n";
|
||||
writeEngineOptions(workspace);
|
||||
|
||||
std::string includeDirsList;
|
||||
for (const std::string &includeDir : setup.includeDirs)
|
||||
includeDirsList += includeDir + ' ';
|
||||
|
||||
workspace << "include_directories(. ${"
|
||||
<< setup.projectDescription << "_SOURCE_DIR}/" << setup.filePrefix
|
||||
<< " ${" << setup.projectDescription << "_SOURCE_DIR}/" << setup.filePrefix << "/engines "
|
||||
<< includeDirsList << "$ENV{"<<LIBS_DEFINE<<"}/include)\n\n";
|
||||
|
||||
workspace << "# Libraries and features\n\n";
|
||||
writeFeatureLibSearch(setup, workspace, "sdl");
|
||||
|
||||
workspace << R"(# Depending on how SDL2 was built, there can be either and imported target or flags variables
|
||||
# Define the flags variables from the imported target if necessary
|
||||
if (TARGET SDL2::SDL2)
|
||||
get_target_property(SDL2_INCLUDE_DIRS SDL2::SDL2 INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(SDL2_LIBRARIES SDL2::SDL2 LOCATION)
|
||||
endif()
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
|
||||
# Explicitly support MacPorts and Homebrew (hopefully harmless on other platforms)
|
||||
link_directories(/opt/local/lib /opt/homebrew/lib)
|
||||
|
||||
)";
|
||||
|
||||
for (const Feature &feature : setup.features) {
|
||||
if (!feature.enable || featureExcluded(feature.name)) continue;
|
||||
|
||||
writeFeatureLibSearch(setup, workspace, feature.name);
|
||||
|
||||
if (!feature.define || !feature.define[0]) continue;
|
||||
workspace << "add_definitions(-D" << feature.define << ")\n";
|
||||
}
|
||||
workspace << "\n";
|
||||
|
||||
writeWarnings(workspace);
|
||||
writeDefines(setup, workspace);
|
||||
|
||||
workspace << R"(# Generate "engines/plugins_table.h"
|
||||
file(REMOVE "engines/plugins_table.h")
|
||||
file(APPEND "engines/plugins_table.h" "/* This file is automatically generated by CMake */\n")
|
||||
|
||||
)";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeFeatureLibSearch(const BuildSetup &setup, std::ofstream &workspace, const char *feature) const {
|
||||
const Library *library = getLibraryFromFeature(feature, setup.useSDL);
|
||||
if (library) {
|
||||
workspace << "find_feature(";
|
||||
workspace << "name " << library->feature;
|
||||
if (library->pkgConfig) {
|
||||
workspace << " pkgconfig_name ";
|
||||
workspace << library->pkgConfig;
|
||||
}
|
||||
if (library->package) {
|
||||
workspace << " findpackage_name ";
|
||||
workspace << library->package;
|
||||
}
|
||||
if (library->includesVar) {
|
||||
workspace << " include_dirs_var ";
|
||||
workspace << library->includesVar;
|
||||
}
|
||||
if (library->librariesVar) {
|
||||
workspace << " libraries_var ";
|
||||
workspace << library->librariesVar;
|
||||
}
|
||||
if (library->libraries) {
|
||||
workspace << " libraries ";
|
||||
workspace << library->libraries;
|
||||
}
|
||||
if (library->winLibraries) {
|
||||
workspace << " win_libraries ";
|
||||
workspace << library->winLibraries;
|
||||
}
|
||||
workspace << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEngines(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
workspace << "set(ENGINES";
|
||||
for (const EngineDesc &engine : setup.engines) {
|
||||
// We ignore all sub engines here because they require special handling.
|
||||
if (!engine.enable || isSubEngine(engine.name, setup.engines)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
workspace << " " << toUpper(engine.name);
|
||||
}
|
||||
workspace << ")\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeSubEngines(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
for (const EngineDesc &engine : setup.engines) {
|
||||
// We ignore all sub engines here because they are handled in the inner loop
|
||||
if (!engine.enable || isSubEngine(engine.name, setup.engines) || engine.subEngines.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
workspace << "set(SUB_ENGINES_" << toUpper(engine.name);
|
||||
for (const std::string &subEngineName : engine.subEngines) {
|
||||
const EngineDesc &subEngine = findEngineDesc(subEngineName, setup.engines);
|
||||
if (!subEngine.enable) continue;
|
||||
workspace << " " << toUpper(subEngineName);
|
||||
}
|
||||
workspace << ")\n";
|
||||
}
|
||||
|
||||
workspace << "\n";
|
||||
}
|
||||
|
||||
static std::string filePrefix(const BuildSetup &setup, const std::string &moduleDir) {
|
||||
std::string modulePath;
|
||||
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
|
||||
modulePath = moduleDir.substr(setup.srcDir.size());
|
||||
if (!modulePath.empty() && modulePath.at(0) == '/')
|
||||
modulePath.erase(0, 1);
|
||||
}
|
||||
return modulePath.empty() ? setup.filePrefix : setup.filePrefix + '/' + modulePath;
|
||||
}
|
||||
|
||||
void CMakeProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
|
||||
const std::string projectFile = setup.outputDir + "/CMakeLists.txt";
|
||||
std::ofstream project(projectFile.c_str(), std::ofstream::out | std::ofstream::app);
|
||||
if (!project)
|
||||
error("Could not open \"" + projectFile + "\" for writing");
|
||||
|
||||
if (name == setup.projectName) {
|
||||
project << "add_executable(" << name;
|
||||
// console subsystem is required for text-console, tools, and tests
|
||||
if (setup.useWindowsSubsystem && !setup.featureEnabled("text-console") && !setup.devTools && !setup.tests) {
|
||||
project << " WIN32";
|
||||
}
|
||||
project << "\n";
|
||||
} else if (name == setup.projectName + "-detection") {
|
||||
project << "list(APPEND SCUMMVM_LIBS " << name << ")\n";
|
||||
project << "add_library(" << name << "\n";
|
||||
} else {
|
||||
enginesStr << "add_engine(" << name << "\n";
|
||||
addFilesToProject(moduleDir, enginesStr, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, filePrefix(setup, moduleDir));
|
||||
enginesStr << ")\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, filePrefix(setup, moduleDir));
|
||||
|
||||
project << ")\n";
|
||||
project << "\n";
|
||||
|
||||
if (name == setup.projectName) {
|
||||
project << "# Engines libraries handling\n";
|
||||
writeEnginesLibrariesHandling(setup, project);
|
||||
|
||||
project << "# Libraries\n";
|
||||
const Library *sdlLibrary = getLibraryFromFeature("sdl", setup.useSDL);
|
||||
std::string libraryDirsList;
|
||||
for (const std::string &libraryDir : setup.libraryDirs)
|
||||
libraryDirsList += libraryDir + ' ';
|
||||
project << "target_link_libraries(" << name << " " << libraryDirsList << "${" << sdlLibrary->librariesVar << "} ${SCUMMVM_LIBS})\n";
|
||||
|
||||
project << "if (WIN32)\n";
|
||||
project << "\ttarget_sources(" << name << " PUBLIC " << setup.filePrefix << "/dists/" << name << ".rc)\n";
|
||||
project << "\ttarget_link_libraries(" << name << " winmm)\n";
|
||||
// Needed for select (used in socket.cpp), when curl is linked dynamically
|
||||
project << "\tif (libcurl_FOUND)\n";
|
||||
project << "\t\ttarget_link_libraries(" << name << " ws2_32)\n";
|
||||
project << "\tendif()\n";
|
||||
project << "endif()\n";
|
||||
project << "\n";
|
||||
|
||||
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD 11)\n";
|
||||
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD_REQUIRED ON)\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProvider::writeWarnings(std::ofstream &output) const {
|
||||
output << "if (MSVC)\n";
|
||||
// TODO: Support MSVC warnings
|
||||
output << "else()\n";
|
||||
output << "\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}";
|
||||
for (const std::string &warning : _globalWarnings) {
|
||||
output << ' ' << warning;
|
||||
}
|
||||
output << "\")\n";
|
||||
output << "\tif(CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\")\n";
|
||||
output << "\t\tif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.1)\n";
|
||||
output << "\t\t\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-stringop-overflow\")\n";
|
||||
output << "\t\tendif()\n";
|
||||
output << "\t\tif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1)\n";
|
||||
output << "\t\t\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-stringop-truncation\")\n";
|
||||
output << "\t\tendif()\n";
|
||||
output << "\t\tif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)\n";
|
||||
output << "\t\t\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member\")\n";
|
||||
output << "\t\tendif()\n";
|
||||
output << "\tendif()\n";
|
||||
output << "endif()\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeDefines(const BuildSetup &setup, std::ofstream &output) const {
|
||||
output << "if (WIN32)\n";
|
||||
output << "\tadd_definitions(-DWIN32)\n";
|
||||
output << "else()\n";
|
||||
output << "\tadd_definitions(-DPOSIX)\n";
|
||||
output << "\t# Hope for the best regarding fseeko and 64-bit off_t\n";
|
||||
output << "\tadd_definitions(-D_FILE_OFFSET_BITS=64)\n";
|
||||
output << "\tadd_definitions(-DHAS_FSEEKO_OFFT_64)\n";
|
||||
output << "endif()\n";
|
||||
|
||||
output << "add_definitions(-DSDL_BACKEND)\n";
|
||||
if (setup.useSDL == kSDLVersion2) {
|
||||
output << "add_definitions(-DUSE_SDL2)\n";
|
||||
} else if (setup.useSDL == kSDLVersion3) {
|
||||
output << "add_definitions(-DUSE_SDL3)\n";
|
||||
}
|
||||
|
||||
if (getFeatureBuildState("opengl", setup.features)) {
|
||||
output << "add_definitions(-DUSE_GLAD)\n";
|
||||
}
|
||||
|
||||
if (setup.useStaticDetection) {
|
||||
output << "add_definitions(-DDETECTION_STATIC)\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
|
||||
std::string lastName;
|
||||
for (const FileNode *node : dir.children) {
|
||||
if (!node->children.empty()) {
|
||||
writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/', pchIncludeRoot, pchDirs, pchExclude);
|
||||
} else {
|
||||
std::string name, ext;
|
||||
splitFilename(node->name, name, ext);
|
||||
if (name != lastName) {
|
||||
if (!lastName.empty()) {
|
||||
projectFile << "\n";
|
||||
}
|
||||
projectFile << "\t";
|
||||
} else {
|
||||
projectFile << " ";
|
||||
}
|
||||
projectFile << filePrefix + node->name;
|
||||
lastName = name;
|
||||
}
|
||||
}
|
||||
projectFile << "\n";
|
||||
}
|
||||
|
||||
const char *CMakeProvider::getProjectExtension() {
|
||||
return ".txt";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEngineOptions(std::ofstream &workspace) const {
|
||||
workspace << "foreach(ENGINE IN LISTS ENGINES)\n";
|
||||
workspace << "\toption(ENABLE_${ENGINE} \"Enable ${ENGINE}\" ON)\n";
|
||||
workspace << "endforeach(ENGINE)\n\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEnginesLibrariesHandling(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
workspace << enginesStr.str();
|
||||
|
||||
}
|
||||
|
||||
bool CMakeProvider::featureExcluded(const char *name) const {
|
||||
return std::strcmp(name, "nasm") == 0 ||
|
||||
std::strcmp(name, "updates") == 0 ; // NASM is not supported for now
|
||||
}
|
||||
|
||||
const EngineDesc &CMakeProvider::findEngineDesc(const std::string &name, const EngineDescList &engines) const {
|
||||
for (const EngineDesc &engine : engines) {
|
||||
if (engine.name == name)
|
||||
return engine;
|
||||
}
|
||||
|
||||
error("Unable to find requested engine");
|
||||
}
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
97
devtools/create_project/cmake.h
Normal file
97
devtools/create_project/cmake.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
#define TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
|
||||
#include "create_project.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
/**
|
||||
* A ProjectProvider used to generate CMake project descriptions
|
||||
*
|
||||
* Generated CMake projects are minimal, and will only work with GCC.
|
||||
*/
|
||||
class CMakeProvider final : public ProjectProvider {
|
||||
public:
|
||||
CMakeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors);
|
||||
|
||||
protected:
|
||||
|
||||
void createWorkspace(const BuildSetup &setup) final;
|
||||
|
||||
void createOtherBuildFiles(const BuildSetup &) final {}
|
||||
|
||||
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final {}
|
||||
|
||||
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
const char *getProjectExtension() final;
|
||||
|
||||
private:
|
||||
std::stringstream enginesStr;
|
||||
|
||||
/**
|
||||
* CMake properties for a library required by a feature
|
||||
*/
|
||||
struct Library {
|
||||
const char *feature;
|
||||
const char *pkgConfig;
|
||||
SDLVersion sdlVersion;
|
||||
const char *module;
|
||||
const char *package;
|
||||
const char *includesVar;
|
||||
const char *librariesVar;
|
||||
const char *libraries;
|
||||
const char *winLibraries;
|
||||
};
|
||||
|
||||
struct LibraryProps : Library {
|
||||
LibraryProps(const char *_feature, const char *_pkgConfig = nullptr, SDLVersion _sdlVersion = kSDLVersionAny) :
|
||||
Library({_feature, _pkgConfig, _sdlVersion, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}) {}
|
||||
LibraryProps &LibrariesVar(const char *var) { librariesVar = var; return *this; }
|
||||
LibraryProps &Libraries(const char *libs) { libraries = libs; return *this; }
|
||||
LibraryProps &WinLibraries(const char *libs) { winLibraries = libs; return *this; }
|
||||
};
|
||||
|
||||
const Library *getLibraryFromFeature(const char *feature, SDLVersion useSDL) const;
|
||||
|
||||
void writeWarnings(std::ofstream &output) const;
|
||||
void writeDefines(const BuildSetup &setup, std::ofstream &output) const;
|
||||
void writeEngines(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeSubEngines(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeEngineOptions(std::ofstream &workspace) const;
|
||||
void writeEnginesLibrariesHandling(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeFeatureLibSearch(const BuildSetup &setup, std::ofstream &workspace, const char *feature) const;
|
||||
bool featureExcluded(const char *name) const;
|
||||
const EngineDesc &findEngineDesc(const std::string &name, const EngineDescList &engines) const;
|
||||
};
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
3
devtools/create_project/cmake/.gitignore
vendored
Normal file
3
devtools/create_project/cmake/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/Makefile
|
||||
/build
|
||||
/create_project*
|
||||
25
devtools/create_project/cmake/CMakeLists.txt
Normal file
25
devtools/create_project/cmake/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(create_project)
|
||||
|
||||
|
||||
set(SOURCE_FILES
|
||||
../cmake.cpp
|
||||
../cmake.h
|
||||
../codeblocks.cpp
|
||||
../codeblocks.h
|
||||
../create_project.cpp
|
||||
../create_project.h
|
||||
../msbuild.cpp
|
||||
../msbuild.h
|
||||
../msvc.cpp
|
||||
../msvc.h
|
||||
../xcode.cpp
|
||||
../xcode.h
|
||||
)
|
||||
|
||||
add_executable(create_project ${SOURCE_FILES})
|
||||
if (WIN32)
|
||||
target_link_libraries(create_project rpcrt4 advapi32)
|
||||
endif ()
|
||||
set_property(TARGET create_project PROPERTY CXX_STANDARD 11)
|
||||
set_property(TARGET create_project PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
288
devtools/create_project/codeblocks.cpp
Normal file
288
devtools/create_project/codeblocks.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "codeblocks.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
CodeBlocksProvider::CodeBlocksProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors)
|
||||
: ProjectProvider(global_warnings, project_warnings, global_errors) {
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::createWorkspace(const BuildSetup &setup) {
|
||||
std::ofstream workspace((setup.outputDir + '/' + setup.projectName + ".workspace").c_str());
|
||||
if (!workspace)
|
||||
error("Could not open \"" + setup.outputDir + '/' + setup.projectName + ".workspace\" for writing");
|
||||
|
||||
workspace << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
|
||||
"<CodeBlocks_workspace_file>\n";
|
||||
|
||||
workspace << "\t<Workspace title=\"" << setup.projectDescription << "\">\n";
|
||||
|
||||
writeReferences(setup, workspace);
|
||||
|
||||
// Note we assume that the UUID map only includes UUIDs for enabled engines!
|
||||
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
|
||||
workspace << "\t\t<Project filename=\"" << i->first << ".cbp\" />\n";
|
||||
}
|
||||
|
||||
workspace << "\t</Workspace>\n"
|
||||
"</CodeBlocks_workspace_file>";
|
||||
}
|
||||
|
||||
StringList getFeatureLibraries(const BuildSetup &setup) {
|
||||
StringList libraries;
|
||||
|
||||
std::string libSDL = "lib";
|
||||
libSDL += setup.getSDLName();
|
||||
libraries.push_back(libSDL);
|
||||
|
||||
for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
|
||||
if (i->enable && i->library) {
|
||||
std::string libname;
|
||||
if (!std::strcmp(i->name, "libcurl")) {
|
||||
libname = i->name;
|
||||
} else if (!std::strcmp(i->name, "zlib")) {
|
||||
libname = "libz";
|
||||
} else if (!std::strcmp(i->name, "vorbis")) {
|
||||
libname = "libvorbis";
|
||||
libraries.push_back("libvorbisfile");
|
||||
} else if (!std::strcmp(i->name, "png")) {
|
||||
libname = "libpng16";
|
||||
} else if (!std::strcmp(i->name, "sdlnet")) {
|
||||
libname = libSDL + "_net";
|
||||
libraries.push_back("iphlpapi");
|
||||
} else {
|
||||
libname = "lib";
|
||||
libname += i->name;
|
||||
}
|
||||
libraries.push_back(libname);
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 libraries
|
||||
libraries.push_back("ole32");
|
||||
libraries.push_back("uuid");
|
||||
libraries.push_back("winmm");
|
||||
|
||||
return libraries;
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
|
||||
const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
|
||||
std::ofstream project(projectFile.c_str());
|
||||
if (!project)
|
||||
error("Could not open \"" + projectFile + "\" for writing");
|
||||
|
||||
project << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
|
||||
"<CodeBlocks_project_file>\n"
|
||||
"\t<FileVersion major=\"1\" minor=\"6\" />\n"
|
||||
"\t<Project>\n"
|
||||
"\t\t<Option title=\"" << name << "\" />\n"
|
||||
"\t\t<Option pch_mode=\"2\" />\n"
|
||||
"\t\t<Option compiler=\"gcc\" />\n"
|
||||
"\t\t<Build>\n";
|
||||
|
||||
if (name == setup.projectName) {
|
||||
StringList libraries = getFeatureLibraries(setup);
|
||||
|
||||
std::string deps;
|
||||
for (StringList::const_iterator i = libraries.begin(); i != libraries.end(); ++i)
|
||||
deps += (*i) + ".a;";
|
||||
|
||||
project << "\t\t\t<Target title=\"default\">\n"
|
||||
"\t\t\t\t<Option output=\"" << setup.projectName << "\\" << setup.projectName << "\" prefix_auto=\"1\" extension_auto=\"1\" />\n"
|
||||
"\t\t\t\t<Option object_output=\"" << setup.projectName << "\" />\n"
|
||||
"\t\t\t\t<Option external_deps=\"" << deps /* + list of engines engines\name\name.a */ << "\" />\n"
|
||||
"\t\t\t\t<Option type=\"1\" />\n"
|
||||
"\t\t\t\t<Option compiler=\"gcc\" />\n"
|
||||
"\t\t\t\t<Option parameters=\"-d 8 --debugflags=parser\" />\n"
|
||||
"\t\t\t\t<Option projectIncludeDirsRelation=\"2\" />\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Compiler
|
||||
project << "\t\t\t\t<Compiler>\n";
|
||||
|
||||
writeWarnings(name, project);
|
||||
writeDefines(setup.defines, project);
|
||||
|
||||
for (StringList::const_iterator i = setup.includeDirs.begin(); i != setup.includeDirs.end(); ++i)
|
||||
project << "\t\t\t\t\t<Add directory=\"" << convertPathToWin(*i) << "\" />\n";
|
||||
|
||||
project << "\t\t\t\t\t<Add directory=\"$(" << LIBS_DEFINE << ")include\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"$(" << LIBS_DEFINE << ")include\\SDL\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\common\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\".\\\" />\n"
|
||||
"\t\t\t\t</Compiler>\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Linker
|
||||
project << "\t\t\t\t<Linker>\n";
|
||||
|
||||
for (StringList::const_iterator i = libraries.begin(); i != libraries.end(); ++i)
|
||||
project << "\t\t\t\t\t<Add library=\"" << (*i) << "\" />\n";
|
||||
|
||||
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
|
||||
project << "\t\t\t\t\t<Add library=\"" << setup.projectName << "\\engines\\" << i->first << "\\lib" << i->first << ".a\" />\n";
|
||||
}
|
||||
|
||||
for (StringList::const_iterator i = setup.libraryDirs.begin(); i != setup.libraryDirs.end(); ++i)
|
||||
project << "\t\t\t\t\t<Add directory=\"" << convertPathToWin(*i) << "\" />\n";
|
||||
|
||||
project << "\t\t\t\t\t<Add directory=\"$(" << LIBS_DEFINE << ")lib\\mingw\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"$(" << LIBS_DEFINE << ")lib\" />\n"
|
||||
"\t\t\t\t</Linker>\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Resource compiler
|
||||
project << "\t\t\t\t<ResourceCompiler>\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\dists\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\..\\" << setup.projectName << "\" />\n"
|
||||
"\t\t\t\t</ResourceCompiler>\n"
|
||||
"\t\t\t</Target>\n"
|
||||
"\t\t</Build>\n";
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
project << "\t\t\t<Target title=\"default\">\n"
|
||||
"\t\t\t\t<Option output=\"" << setup.projectName << "\\engines\\" << name << "\\lib" << name << "\" prefix_auto=\"1\" extension_auto=\"1\" />\n"
|
||||
"\t\t\t\t<Option working_dir=\"\" />\n"
|
||||
"\t\t\t\t<Option object_output=\"" << setup.projectName << "\" />\n"
|
||||
"\t\t\t\t<Option type=\"2\" />\n"
|
||||
"\t\t\t\t<Option compiler=\"gcc\" />\n"
|
||||
"\t\t\t\t<Option createDefFile=\"1\" />\n"
|
||||
"\t\t\t\t<Compiler>\n";
|
||||
|
||||
writeWarnings(name, project);
|
||||
writeDefines(setup.defines, project);
|
||||
|
||||
project << "\t\t\t\t\t<Add option=\"-g\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
|
||||
"\t\t\t\t\t<Add directory=\"..\\..\\..\\" << setup.projectName << "\" />\n";
|
||||
|
||||
// Sword2.5 engine needs theora and vorbis includes
|
||||
if (name == "sword25")
|
||||
project << "\t\t\t\t\t<Add directory=\"$(" << LIBS_DEFINE << ")include\" />\n";
|
||||
|
||||
project << "\t\t\t\t</Compiler>\n"
|
||||
"\t\t\t</Target>\n"
|
||||
"\t\t</Build>\n";
|
||||
}
|
||||
|
||||
std::string modulePath;
|
||||
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
|
||||
modulePath = moduleDir.substr(setup.srcDir.size());
|
||||
if (!modulePath.empty() && modulePath.at(0) == '/')
|
||||
modulePath.erase(0, 1);
|
||||
}
|
||||
|
||||
if (!modulePath.empty())
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix + '/' + modulePath);
|
||||
else
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix);
|
||||
|
||||
|
||||
project << "\t\t<Extensions>\n"
|
||||
"\t\t\t<code_completion />\n"
|
||||
"\t\t\t<debugger />\n"
|
||||
"\t\t</Extensions>\n"
|
||||
"\t</Project>\n"
|
||||
"</CodeBlocks_project_file>";
|
||||
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
|
||||
includeList.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
|
||||
includeList.push_back(setup.srcDir + "/dists/" + setup.projectName + ".rc");
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::writeWarnings(const std::string &name, std::ofstream &output) const {
|
||||
|
||||
// Global warnings
|
||||
for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i)
|
||||
output << "\t\t\t\t\t<Add option=\"" << *i << "\" />\n";
|
||||
|
||||
// Check for project-specific warnings:
|
||||
std::map<std::string, StringList>::iterator warningsIterator = _projectWarnings.find(name);
|
||||
if (warningsIterator != _projectWarnings.end())
|
||||
for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
|
||||
output << "\t\t\t\t\t<Add option=\"" << *i << "\" />\n";
|
||||
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::writeDefines(const StringList &defines, std::ofstream &output) const {
|
||||
for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i)
|
||||
output << "\t\t\t\t\t<Add option=\"-D" << *i << "\" />\n";
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
|
||||
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
|
||||
const FileNode *node = *i;
|
||||
|
||||
if (!node->children.empty()) {
|
||||
writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/', pchIncludeRoot, pchDirs, pchExclude);
|
||||
} else {
|
||||
std::string name, ext;
|
||||
splitFilename(node->name, name, ext);
|
||||
|
||||
if (ext == "rc") {
|
||||
projectFile << "\t\t<Unit filename=\"" << convertPathToWin(filePrefix + node->name) << "\">\n"
|
||||
"\t\t\t<Option compilerVar=\"WINDRES\" />\n"
|
||||
"\t\t</Unit>\n";
|
||||
} else if (ext == "asm") {
|
||||
projectFile << "\t\t<Unit filename=\"" << convertPathToWin(filePrefix + node->name) << "\">\n"
|
||||
"\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"$(" << LIBS_DEFINE << ")bin/nasm.exe -f win32 -g $file -o $object\" />"
|
||||
"\t\t</Unit>\n";
|
||||
} else {
|
||||
projectFile << "\t\t<Unit filename=\"" << convertPathToWin(filePrefix + node->name) << "\" />\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CodeBlocksProvider::writeReferences(const BuildSetup &setup, std::ofstream &output) {
|
||||
output << "\t\t<Project filename=\"" << setup.projectName << ".cbp\" active=\"1\">\n";
|
||||
|
||||
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
|
||||
output << "\t\t\t<Depends filename=\"" << i->first << ".cbp\" />\n";
|
||||
}
|
||||
|
||||
output << "\t\t</Project>\n";
|
||||
}
|
||||
|
||||
const char *CodeBlocksProvider::getProjectExtension() {
|
||||
return ".cbp";
|
||||
}
|
||||
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
59
devtools/create_project/codeblocks.h
Normal file
59
devtools/create_project/codeblocks.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_CODEBLOCKS_H
|
||||
#define TOOLS_CREATE_PROJECT_CODEBLOCKS_H
|
||||
|
||||
#include "create_project.h"
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
class CodeBlocksProvider final : public ProjectProvider {
|
||||
public:
|
||||
CodeBlocksProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors);
|
||||
|
||||
protected:
|
||||
|
||||
void createWorkspace(const BuildSetup &setup) final;
|
||||
|
||||
void createOtherBuildFiles(const BuildSetup &) final {}
|
||||
|
||||
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final;
|
||||
|
||||
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
void writeReferences(const BuildSetup &setup, std::ofstream &output) final;
|
||||
|
||||
const char *getProjectExtension() final;
|
||||
|
||||
private:
|
||||
void writeWarnings(const std::string &name, std::ofstream &output) const;
|
||||
void writeDefines(const StringList &defines, std::ofstream &output) const;
|
||||
};
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_CODEBLOCKS_H
|
||||
59
devtools/create_project/codeblocks/create_project.cbp
Normal file
59
devtools/create_project/codeblocks/create_project.cbp
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="create_project" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin\Debug\create_project" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Debug\" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="rpcrt4" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="bin\Release\create_project" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Release\" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add library="rpcrt4" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-fexceptions" />
|
||||
</Compiler>
|
||||
<Unit filename="..\config.h" />
|
||||
<Unit filename="..\cmake.cpp" />
|
||||
<Unit filename="..\cmake.h" />
|
||||
<Unit filename="..\codeblocks.cpp" />
|
||||
<Unit filename="..\codeblocks.h" />
|
||||
<Unit filename="..\create_project.cpp" />
|
||||
<Unit filename="..\create_project.h" />
|
||||
<Unit filename="..\msbuild.cpp" />
|
||||
<Unit filename="..\msbuild.h" />
|
||||
<Unit filename="..\msvc.cpp" />
|
||||
<Unit filename="..\msvc.h" />
|
||||
<Unit filename="..\xcode.cpp" />
|
||||
<Unit filename="..\xcode.h" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
<lib_finder disable_auto="1" />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
36
devtools/create_project/config.h
Normal file
36
devtools/create_project/config.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_CONFIG_H
|
||||
#define TOOLS_CREATE_PROJECT_CONFIG_H
|
||||
|
||||
#define PROJECT_DESCRIPTION "ScummVM" // Used in console output and build configuration
|
||||
#define PROJECT_NAME "scummvm" // Used for folders, icons, resources and project/solution name
|
||||
#define LIBS_DEFINE "SCUMMVM_LIBS" // Name of the include environment variable
|
||||
#define REVISION_DEFINE "SCUMMVM_INTERNAL_REVISION"
|
||||
#define FIRST_ENGINE "scumm" // Name of the engine which should be sorted as first element
|
||||
|
||||
#define ENABLE_LANGUAGE_EXTENSIONS "" // Comma separated list of projects that need language extensions
|
||||
#define DISABLE_EDIT_AND_CONTINUE "tinsel,tony,scummvm" // Comma separated list of projects that need Edit&Continue to be disabled for co-routine support (the main project is automatically added)
|
||||
|
||||
#define NEEDS_RTTI 1 // Enable RTTI globally
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_CONFIG_H
|
||||
2784
devtools/create_project/create_project.cpp
Normal file
2784
devtools/create_project/create_project.cpp
Normal file
File diff suppressed because it is too large
Load Diff
753
devtools/create_project/create_project.h
Normal file
753
devtools/create_project/create_project.h
Normal file
@@ -0,0 +1,753 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_H
|
||||
#define TOOLS_CREATE_PROJECT_H
|
||||
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#error MSVC support requires MSVC 2015 or newer
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
typedef std::list<std::string> StringList;
|
||||
|
||||
typedef StringList TokenList;
|
||||
|
||||
/**
|
||||
* Takes a given input line and creates a list of tokens out of it.
|
||||
*
|
||||
* A token in this context is separated by whitespaces. A special case
|
||||
* are quotation marks though. A string inside quotation marks is treated
|
||||
* as single token, even when it contains whitespaces.
|
||||
*
|
||||
* Thus for example the input:
|
||||
* foo bar "1 2 3 4" ScummVM
|
||||
* will create a list with the following entries:
|
||||
* "foo", "bar", "1 2 3 4", "ScummVM"
|
||||
* As you can see the quotation marks will get *removed* too.
|
||||
*
|
||||
* You can also use this with non-whitespace by passing another separator
|
||||
* character (e.g. ',').
|
||||
*
|
||||
* @param input The text to be tokenized.
|
||||
* @param separator The token separator.
|
||||
* @return A list of tokens.
|
||||
*/
|
||||
TokenList tokenize(const std::string &input, char separator = ' ');
|
||||
|
||||
/**
|
||||
* Structure to describe a game engine to be built into ScummVM.
|
||||
*
|
||||
* We do get the game engines available by parsing the "configure"
|
||||
* script of our source distribution. See "parseConfigure" for more
|
||||
* information on that.
|
||||
* @see parseConfigure
|
||||
*/
|
||||
struct EngineDesc {
|
||||
/**
|
||||
* The name of the engine. We use this to determine the directory
|
||||
* the engine is in and to create the define, which needs to be
|
||||
* set to enable the engine.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* A human readable description of the engine. We will use this
|
||||
* to display a description of the engine to the user in the list
|
||||
* of which engines are built and which are disabled.
|
||||
*/
|
||||
std::string desc;
|
||||
|
||||
/**
|
||||
* Whether the engine should be included in the build or not.
|
||||
*/
|
||||
bool enable = false;
|
||||
|
||||
/**
|
||||
* Features required for this engine.
|
||||
*/
|
||||
StringList requiredFeatures;
|
||||
|
||||
/**
|
||||
* Components wished for this engine.
|
||||
*/
|
||||
StringList wishedComponents;
|
||||
|
||||
/**
|
||||
* A list of all available sub engine names. Sub engines are engines
|
||||
* which are built on top of an existing engines and can be only
|
||||
* enabled when the parten engine is enabled.
|
||||
*/
|
||||
StringList subEngines;
|
||||
|
||||
bool operator==(const std::string &n) const {
|
||||
return (name == n);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<EngineDesc> EngineDescList;
|
||||
|
||||
/**
|
||||
* This function parses the project directory and creates a list of
|
||||
* available engines.
|
||||
*
|
||||
* It will also automatically setup the default build state (enabled
|
||||
* or disabled) to the state specified in the individual configure.engine
|
||||
* files.
|
||||
*
|
||||
* @param srcDir Path to the root of the project source.
|
||||
* @return List of available engines.
|
||||
*/
|
||||
EngineDescList parseEngines(const std::string &srcDir);
|
||||
|
||||
/**
|
||||
* Checks whether the specified engine is a sub engine. To determine this
|
||||
* there is a fully setup engine list needed.
|
||||
*
|
||||
* @param name Name of the engine to check.
|
||||
* @param engines List of engines.
|
||||
* @return "true", when the engine is a sub engine, "false" otherwise.
|
||||
*/
|
||||
bool isSubEngine(const std::string &name, const EngineDescList &engines);
|
||||
|
||||
/**
|
||||
* Enables or disables the specified engine in the engines list.
|
||||
*
|
||||
* This function also disables all sub engines of an engine, when it is
|
||||
* to be disabled.
|
||||
* Also this function does enable the parent of a sub engine, when a
|
||||
* sub engine is to be enabled.
|
||||
*
|
||||
* @param name Name of the engine to be enabled or disabled.
|
||||
* @param engines The list of engines, which should be operated on.
|
||||
* @param enable Whether the engine should be enabled or disabled.
|
||||
* @return "true", when it succeeded, "false" otherwise.
|
||||
*/
|
||||
bool setEngineBuildState(const std::string &name, EngineDescList &engines, bool enable);
|
||||
|
||||
/**
|
||||
* Returns a list of all defines, according to the engine list passed.
|
||||
*
|
||||
* @param features The list of engines, which should be operated on. (this may contain engines, which are *not* enabled!)
|
||||
*/
|
||||
StringList getEngineDefines(const EngineDescList &engines);
|
||||
|
||||
/**
|
||||
* Structure to define a given feature, usually an external library,
|
||||
* used to build ScummVM.
|
||||
*/
|
||||
struct Feature {
|
||||
const char *name; ///< Name of the feature
|
||||
const char *define; ///< Define of the feature
|
||||
bool library; ///< Whether this feature needs to be linked to a library
|
||||
|
||||
bool enable; ///< Whether the feature is enabled or not
|
||||
|
||||
const char *description; ///< Human readable description of the feature
|
||||
|
||||
bool operator==(const std::string &n) const {
|
||||
return (name == n);
|
||||
}
|
||||
};
|
||||
typedef std::list<Feature> FeatureList;
|
||||
|
||||
struct Component {
|
||||
std::string name; ///< Name of the component
|
||||
std::string define; ///< Define of the component
|
||||
|
||||
Feature &feature; ///< Associated feature
|
||||
|
||||
std::string description; ///< Human readable description of the component
|
||||
|
||||
bool needed;
|
||||
|
||||
bool operator==(const std::string &n) const {
|
||||
return (name == n);
|
||||
}
|
||||
};
|
||||
typedef std::list<Component> ComponentList;
|
||||
|
||||
struct Tool {
|
||||
const char *name; ///< Name of the tools
|
||||
bool enable; ///< Whether the tools is enabled or not
|
||||
};
|
||||
typedef std::list<Tool> ToolList;
|
||||
|
||||
/**
|
||||
* Creates a list of all features available for MSVC.
|
||||
*
|
||||
* @return A list including all features available.
|
||||
*/
|
||||
FeatureList getAllFeatures();
|
||||
|
||||
/**
|
||||
* Creates a list of all components.
|
||||
*
|
||||
* @param srcDir The source directory containing the configure script
|
||||
* @param features The features list used to link the component to its feature
|
||||
*
|
||||
* @return A list including all components available linked to its features.
|
||||
*/
|
||||
ComponentList getAllComponents(const std::string &srcDir, FeatureList &features);
|
||||
|
||||
/**
|
||||
* Disable the features for the unused components.
|
||||
*
|
||||
* @param components List of components for the build
|
||||
*/
|
||||
void disableComponents(const ComponentList &components);
|
||||
|
||||
/**
|
||||
* Returns a list of all defines, according to the feature set
|
||||
* passed.
|
||||
*
|
||||
* @param features List of features for the build (this may contain features, which are *not* enabled!)
|
||||
*/
|
||||
StringList getFeatureDefines(const FeatureList &features);
|
||||
|
||||
/**
|
||||
* Sets the state of a given feature. This can be used to
|
||||
* either include or exclude a feature.
|
||||
*
|
||||
* @param name Name of the feature.
|
||||
* @param features List of features to operate on.
|
||||
* @param enable Whether the feature should be enabled or disabled.
|
||||
* @return "true", when it succeeded, "false" otherwise.
|
||||
*/
|
||||
bool setFeatureBuildState(const std::string &name, FeatureList &features, bool enable);
|
||||
|
||||
/**
|
||||
* Gets the state of a given feature.
|
||||
*
|
||||
* @param name Name of the feature.
|
||||
* @param features List of features to operate on.
|
||||
* @return "true", when the feature is enabled, "false" otherwise.
|
||||
*/
|
||||
bool getFeatureBuildState(const std::string &name, const FeatureList &features);
|
||||
|
||||
/**
|
||||
* Specifies the required SDL version of a feature.
|
||||
*/
|
||||
enum SDLVersion {
|
||||
kSDLVersionAny = 0,
|
||||
kSDLVersion1, ///< SDL 1.2
|
||||
kSDLVersion2, ///< SDL 2
|
||||
kSDLVersion3 ///< SDL 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure to describe a build setup.
|
||||
*
|
||||
* This includes various information about which engines to
|
||||
* enable, which features should be built into the main executable.
|
||||
* It also contains the path to the project source root.
|
||||
*/
|
||||
struct BuildSetup {
|
||||
std::string projectName; ///< Project name
|
||||
std::string projectDescription; ///< Project description
|
||||
|
||||
std::string srcDir; ///< Path to the sources.
|
||||
std::string filePrefix; ///< Prefix for the relative path arguments in the project files.
|
||||
std::string outputDir; ///< Path where to put the MSVC project files.
|
||||
std::string libsDir; ///< Path to libraries for MSVC builds. If absent, use LIBS_DEFINE environment var instead.
|
||||
|
||||
StringList includeDirs; ///< List of additional include paths
|
||||
StringList libraryDirs; ///< List of additional library paths
|
||||
|
||||
EngineDescList engines; ///< Engine list for the build (this may contain engines, which are *not* enabled!).
|
||||
FeatureList features; ///< Feature list for the build (this may contain features, which are *not* enabled!).
|
||||
|
||||
ComponentList components;
|
||||
|
||||
StringList defines; ///< List of all defines for the build.
|
||||
StringList testDirs; ///< List of all folders containing tests
|
||||
|
||||
bool devTools = false; ///< Generate project files for the tools
|
||||
bool tests = false; ///< Generate project files for the tests
|
||||
bool runBuildEvents = false; ///< Run build events as part of the build (generate revision number and copy engine/theme data & needed files to the build folder
|
||||
bool createInstaller = false; ///< Create installer after the build
|
||||
SDLVersion useSDL = kSDLVersion2; ///< Which version of SDL to use.
|
||||
bool useStaticDetection = true; ///< Whether to link detection features inside the executable or not.
|
||||
bool useWindowsUnicode = true; ///< Whether to use Windows Unicode APIs or ANSI APIs.
|
||||
bool useWindowsSubsystem = false; ///< Whether to use Windows subsystem or Console subsystem (default: Console)
|
||||
bool appleEmbedded = false; ///< Whether the build will target iOS or tvOS instead of macOS.
|
||||
bool useXCFramework = false; ///< Whether to use Apple XCFrameworks instead of static libraries
|
||||
bool useVcpkg = false; ///< Whether to load libraries from vcpkg or SCUMMVM_LIBS
|
||||
bool useSlnx = false; ///< Whether to use old .sln or new .slnx format
|
||||
bool win32 = false; ///< Target is Windows
|
||||
|
||||
bool featureEnabled(const std::string &feature) const;
|
||||
Feature getFeature(const std::string &feature) const;
|
||||
const char *getSDLName() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quits the program with the specified error message.
|
||||
*
|
||||
* @param message The error message to print to stderr.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define NORETURN_POST __attribute__((__noreturn__))
|
||||
#elif defined(_MSC_VER)
|
||||
#define NORETURN_PRE __declspec(noreturn)
|
||||
#endif
|
||||
|
||||
#ifndef NORETURN_PRE
|
||||
#define NORETURN_PRE
|
||||
#endif
|
||||
|
||||
#ifndef NORETURN_POST
|
||||
#define NORETURN_POST
|
||||
#endif
|
||||
void NORETURN_PRE error(const std::string &message) NORETURN_POST;
|
||||
|
||||
/**
|
||||
* Structure to describe a Visual Studio version specification.
|
||||
*
|
||||
* This includes various generation details for MSVC projects,
|
||||
* as well as describe the versions supported.
|
||||
*/
|
||||
struct MSVCVersion {
|
||||
int version; ///< Version number passed as parameter.
|
||||
const char *name; ///< Full program name.
|
||||
const char *solutionFormat; ///< Format used for solution files.
|
||||
const char *solutionVersion; ///< Version number used in solution files.
|
||||
const char *project; ///< Version number used in project files.
|
||||
const char *toolsetMSVC; ///< Toolset version for MSVC compiler.
|
||||
const char *toolsetLLVM; ///< Toolset version for Clang/LLVM compiler.
|
||||
};
|
||||
typedef std::list<MSVCVersion> MSVCList;
|
||||
|
||||
enum MSVC_Architecture {
|
||||
ARCH_ARM64,
|
||||
ARCH_X86,
|
||||
ARCH_AMD64
|
||||
};
|
||||
|
||||
std::string getMSVCArchName(MSVC_Architecture arch);
|
||||
std::string getMSVCConfigName(MSVC_Architecture arch);
|
||||
|
||||
enum EngineDataGroup {
|
||||
kEngineDataGroupNormal,
|
||||
kEngineDataGroupCore,
|
||||
kEngineDataGroupBig,
|
||||
|
||||
kEngineDataGroupCount,
|
||||
};
|
||||
|
||||
struct EngineDataGroupResolution {
|
||||
EngineDataGroup engineDataGroup;
|
||||
const char *mkFilePath;
|
||||
const char *winHeaderPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a list of all supported versions of Visual Studio.
|
||||
*
|
||||
* @return A list including all versions available.
|
||||
*/
|
||||
MSVCList getAllMSVCVersions();
|
||||
|
||||
/**
|
||||
* Returns the definitions for a specific Visual Studio version.
|
||||
*
|
||||
* @param version The requested version.
|
||||
* @return The version information, or NULL if the version isn't supported.
|
||||
*/
|
||||
const MSVCVersion *getMSVCVersion(int version);
|
||||
|
||||
/**
|
||||
* Auto-detects the latest version of Visual Studio installed.
|
||||
*
|
||||
* @return Version number, or 0 if no installations were found.
|
||||
*/
|
||||
int getInstalledMSVC();
|
||||
|
||||
/**
|
||||
* Removes given feature from setup.
|
||||
*
|
||||
* @param setup The setup to be processed.
|
||||
* @param feature The feature to be removed
|
||||
* @return A copy of setup less feature.
|
||||
*/
|
||||
BuildSetup removeFeatureFromSetup(BuildSetup setup, const std::string &feature);
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
/**
|
||||
* Structure for describing an FSNode. This is a very minimalistic
|
||||
* description, which includes everything we need.
|
||||
* It only contains the name of the node and whether it is a directory
|
||||
* or not.
|
||||
*/
|
||||
struct FSNode {
|
||||
FSNode() : name(), isDirectory(false) {}
|
||||
FSNode(const std::string &n, bool iD) : name(n), isDirectory(iD) {}
|
||||
|
||||
std::string name; ///< Name of the file system node
|
||||
bool isDirectory; ///< Whether it is a directory or not
|
||||
};
|
||||
|
||||
typedef std::list<FSNode> FileList;
|
||||
|
||||
/**
|
||||
* Gets a proper sequence of \t characters for the given
|
||||
* indentation level.
|
||||
*
|
||||
* For example with an indentation level of 2 this will
|
||||
* produce:
|
||||
* \t\t
|
||||
*
|
||||
* @param indentation The indentation level
|
||||
* @return Sequence of \t characters.
|
||||
*/
|
||||
std::string getIndent(const int indentation);
|
||||
|
||||
/**
|
||||
* Converts the given path to only use backslashes.
|
||||
* This means that for example the path:
|
||||
* foo/bar\test.txt
|
||||
* will be converted to:
|
||||
* foo\bar\test.txt
|
||||
*
|
||||
* @param path Path string.
|
||||
* @return Converted path.
|
||||
*/
|
||||
std::string convertPathToWin(const std::string &path);
|
||||
|
||||
/**
|
||||
* Splits a file name into name and extension.
|
||||
* The file name must be only the filename, no
|
||||
* additional path name.
|
||||
*
|
||||
* @param fileName Filename to split
|
||||
* @param name Reference to a string, where to store the name.
|
||||
* @param ext Reference to a string, where to store the extension.
|
||||
*/
|
||||
void splitFilename(const std::string &fileName, std::string &name, std::string &ext);
|
||||
|
||||
/**
|
||||
* Splits a full path into directory and filename.
|
||||
* This assumes the last part is the filename, even if it
|
||||
* has no extension.
|
||||
*
|
||||
* @param path Path to split
|
||||
* @param name Reference to a string, where to store the directory part.
|
||||
* @param ext Reference to a string, where to store the filename part.
|
||||
*/
|
||||
void splitPath(const std::string &path, std::string &dir, std::string &file);
|
||||
|
||||
/**
|
||||
* Calculates the include path and PCH file path (without the base directory).
|
||||
*
|
||||
* @param filePath Path to the source file.
|
||||
* @param pchIncludeRoot Path to the PCH inclusion root directory (ending with separator).
|
||||
* @param pchDirs List of PCH directories.
|
||||
* @param pchExclude List of PCH exclusions.
|
||||
* @param separator Path separator
|
||||
* @param outPchIncludePath Output path to be used by #include directives.
|
||||
* @param outPchFilePath Output file path.
|
||||
* @param outPchFileName Output file name.
|
||||
* @return True if the file path uses PCH, false if not.
|
||||
*/
|
||||
bool calculatePchPaths(const std::string &sourceFilePath, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, char separator, std::string &outPchIncludePath, std::string &outPchFilePath, std::string &outPchFileName);
|
||||
|
||||
/**
|
||||
* Returns the basename of a path.
|
||||
* examples:
|
||||
* a/b/c/d.ext -> d.ext
|
||||
* d.ext -> d.ext
|
||||
*
|
||||
* @param fileName Filename
|
||||
* @return The basename
|
||||
*/
|
||||
std::string basename(const std::string &fileName);
|
||||
|
||||
/**
|
||||
* Checks whether the given file will produce an object file or not.
|
||||
*
|
||||
* @param fileName Name of the file.
|
||||
* @return "true" when it will produce a file, "false" otherwise.
|
||||
*/
|
||||
bool producesObjectFile(const std::string &fileName);
|
||||
|
||||
/**
|
||||
* Convert an integer to string
|
||||
*
|
||||
* @param num the integer to convert
|
||||
* @return string representation of the number
|
||||
*/
|
||||
std::string toString(int num);
|
||||
|
||||
/**
|
||||
* Convert a string to uppercase
|
||||
*
|
||||
* @param str the source string
|
||||
* @return The string transformed to uppercase
|
||||
*/
|
||||
std::string toUpper(const std::string &str);
|
||||
|
||||
/**
|
||||
* Returns a list of all files and directories in the specified
|
||||
* path.
|
||||
*
|
||||
* @param dir Directory which should be listed.
|
||||
* @return List of all children.
|
||||
*/
|
||||
FileList listDirectory(const std::string &dir);
|
||||
|
||||
/**
|
||||
* Create a directory at the given path.
|
||||
*
|
||||
* @param dir The path to create.
|
||||
*/
|
||||
void createDirectory(const std::string &dir);
|
||||
|
||||
/**
|
||||
* Structure representing a file tree. This contains two
|
||||
* members: name and children. "name" holds the name of
|
||||
* the node. "children" does contain all the node's children.
|
||||
* When the list "children" is empty, the node is a file entry,
|
||||
* otherwise it's a directory.
|
||||
*/
|
||||
struct FileNode {
|
||||
typedef std::list<FileNode *> NodeList;
|
||||
|
||||
explicit FileNode(const std::string &n) : name(n), children() {}
|
||||
|
||||
~FileNode() {
|
||||
for (NodeList::iterator i = children.begin(); i != children.end(); ++i)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
std::string name; ///< Name of the node
|
||||
NodeList children; ///< List of children for the node
|
||||
};
|
||||
|
||||
class ProjectProvider {
|
||||
public:
|
||||
struct EngineDataGroupDef {
|
||||
StringList dataFiles;
|
||||
std::string winHeaderPath;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::string> UUIDMap;
|
||||
|
||||
/**
|
||||
* Instantiate new ProjectProvider class
|
||||
*
|
||||
* @param global_warnings List of warnings that apply to all projects
|
||||
* @param project_warnings List of project-specific warnings
|
||||
* @param version Target project version.
|
||||
*/
|
||||
ProjectProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors);
|
||||
virtual ~ProjectProvider() {}
|
||||
|
||||
/**
|
||||
* Creates all build files
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
void createProject(BuildSetup &setup);
|
||||
|
||||
/**
|
||||
* Returns the last path component.
|
||||
*
|
||||
* @param path Path string.
|
||||
* @return Last path component.
|
||||
*/
|
||||
static std::string getLastPathComponent(const std::string &path);
|
||||
|
||||
protected:
|
||||
StringList &_globalWarnings; ///< Global (ignored) warnings
|
||||
StringList &_globalErrors; ///< Global errors (promoted from warnings)
|
||||
std::map<std::string, StringList> &_projectWarnings; ///< Per-project warnings
|
||||
|
||||
UUIDMap _engineUuidMap; ///< List of (project name, UUID) pairs
|
||||
UUIDMap _allProjUuidMap;
|
||||
|
||||
EngineDataGroupDef _engineDataGroupDefs[kEngineDataGroupCount];
|
||||
|
||||
/**
|
||||
* Create workspace/solution file
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
virtual void createWorkspace(const BuildSetup &setup) = 0;
|
||||
|
||||
/**
|
||||
* Create other files (such as build properties)
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
virtual void createOtherBuildFiles(const BuildSetup &setup) = 0;
|
||||
|
||||
/**
|
||||
* Add resources to the project
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
virtual void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) = 0;
|
||||
|
||||
/**
|
||||
* Create a project file for the specified list of files.
|
||||
*
|
||||
* @param name Name of the project file.
|
||||
* @param uuid UUID of the project file.
|
||||
* @param setup Description of the desired build.
|
||||
* @param moduleDir Path to the module.
|
||||
* @param includeList Files to include (must have "moduleDir" as prefix).
|
||||
* @param excludeList Files to exclude (must have "moduleDir" as prefix).
|
||||
*/
|
||||
virtual void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) = 0;
|
||||
|
||||
/**
|
||||
* Writes file entries for the specified directory node into
|
||||
* the given project file.
|
||||
*
|
||||
* @param dir Directory node.
|
||||
* @param projectFile File stream to write to.
|
||||
* @param indentation Indentation level to use.
|
||||
* @param objPrefix Prefix to use for object files, which would name clash.
|
||||
* @param filePrefix Generic prefix to all files of the node.
|
||||
*/
|
||||
virtual void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) = 0;
|
||||
|
||||
/**
|
||||
* Output a list of project references to the file stream
|
||||
*
|
||||
* @param output File stream to write to.
|
||||
*/
|
||||
virtual void writeReferences(const BuildSetup &, std::ofstream &) {}
|
||||
|
||||
/**
|
||||
* Get the file extension for project files
|
||||
*/
|
||||
virtual const char *getProjectExtension() { return ""; }
|
||||
|
||||
/**
|
||||
* Adds files of the specified directory recursively to given project file.
|
||||
*
|
||||
* @param dir Path to the directory.
|
||||
* @param projectFile Output stream object, where all data should be written to.
|
||||
* @param includeList Files to include (must have a relative directory as prefix).
|
||||
* @param excludeList Files to exclude (must have a relative directory as prefix).
|
||||
* @param filePrefix Prefix to use for relative path arguments.
|
||||
*/
|
||||
void addFilesToProject(const std::string &dir, std::ostream &projectFile,
|
||||
const StringList &includeList, const StringList &excludeList,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude,
|
||||
const std::string &filePrefix);
|
||||
|
||||
/**
|
||||
* Creates a list of files of the specified module. This also
|
||||
* creates a list of files, which should not be included.
|
||||
* All filenames will have "moduleDir" as prefix.
|
||||
*
|
||||
* @param moduleDir Path to the module.
|
||||
* @param defines List of set defines.
|
||||
* @param testDirs List of folders containing tests.
|
||||
* @param includeList Reference to a list, where included files should be added.
|
||||
* @param excludeList Reference to a list, where excluded files should be added.
|
||||
*/
|
||||
void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList, StringList &pchDirs, StringList &pchExclude, bool forDetection = false) const;
|
||||
|
||||
/**
|
||||
* Creates a list of data files from a specified .mk file
|
||||
*
|
||||
* @param makeFilePath Path to the engine data makefile.
|
||||
* @param defines List of set defines.
|
||||
* @param outDataFiles Output list of data files.
|
||||
* @param outWinHeaderPath Output Windows resource header path.
|
||||
*/
|
||||
void createDataFilesList(EngineDataGroup engineDataGroup, const std::string &baseDir, const StringList &defines, StringList &outDataFiles, std::string &outWinHeaderPath) const;
|
||||
|
||||
/**
|
||||
* Creates an UUID for every enabled engine of the
|
||||
* passed build description.
|
||||
*
|
||||
* @param setup Description of the desired build.
|
||||
* @return A map, which includes UUIDs for all enabled engines.
|
||||
*/
|
||||
UUIDMap createUUIDMap(const BuildSetup &setup) const;
|
||||
|
||||
/**
|
||||
* Creates an UUID for every enabled tool of the
|
||||
* passed build description.
|
||||
*
|
||||
* @return A map, which includes UUIDs for all enabled tools.
|
||||
*/
|
||||
UUIDMap createToolsUUIDMap() const;
|
||||
|
||||
/**
|
||||
* Creates an UUID and returns it in string representation.
|
||||
*
|
||||
* @return A new UUID as string.
|
||||
*/
|
||||
std::string createUUID() const;
|
||||
|
||||
/**
|
||||
* Creates a name-based UUID and returns it in string representation.
|
||||
*
|
||||
* @param name Unique name to hash.
|
||||
* @return A new UUID as string.
|
||||
*/
|
||||
std::string createUUID(const std::string &name) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the string representation of an existing UUID.
|
||||
*
|
||||
* @param uuid 128-bit array.
|
||||
* @return Existing UUID as string.
|
||||
*/
|
||||
std::string UUIDToString(unsigned char *uuid) const;
|
||||
|
||||
/**
|
||||
* This creates the engines/plugins_table.h file required for building
|
||||
* ScummVM.
|
||||
*
|
||||
* @param setup Description of the desired build.
|
||||
*/
|
||||
void createEnginePluginsTable(const BuildSetup &setup);
|
||||
|
||||
/**
|
||||
* Creates resource embed files
|
||||
*/
|
||||
void createResourceEmbeds(const BuildSetup &setup) const;
|
||||
};
|
||||
|
||||
} // namespace CreateProjectTool
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_H
|
||||
24
devtools/create_project/module.mk
Normal file
24
devtools/create_project/module.mk
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
MODULE := devtools/create_project
|
||||
|
||||
MODULE_OBJS := \
|
||||
cmake.o \
|
||||
create_project.o \
|
||||
codeblocks.o \
|
||||
msvc.o \
|
||||
msbuild.o \
|
||||
xcode.o
|
||||
|
||||
# Set the name of the executable
|
||||
TOOL_EXECUTABLE := create_project
|
||||
|
||||
# Set custom build flags for create_project.o: It uses C++ iostreams,
|
||||
# which make use of global constructors. So we don't want warnings for
|
||||
# that.
|
||||
$(srcdir)/devtools/create_project/create_project.o: CXXFLAGS:=$(filter-out -Wglobal-constructors,$(CXXFLAGS))
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Silence variadic macros warning for C++ (disabled as this is included globally)
|
||||
#CXXFLAGS := $(CXXFLAGS) -Wno-variadic-macros
|
||||
821
devtools/create_project/msbuild.cpp
Normal file
821
devtools/create_project/msbuild.cpp
Normal file
@@ -0,0 +1,821 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "msbuild.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MSBuild Provider (Visual Studio 2010 and later)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MSBuildProvider::MSBuildProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors, const int version, const MSVCVersion &msvc)
|
||||
: MSVCProvider(global_warnings, project_warnings, global_errors, version, msvc) {
|
||||
|
||||
_archs.push_back(ARCH_X86);
|
||||
_archs.push_back(ARCH_AMD64);
|
||||
_archs.push_back(ARCH_ARM64);
|
||||
}
|
||||
|
||||
const char *MSBuildProvider::getProjectExtension() {
|
||||
return ".vcxproj";
|
||||
}
|
||||
|
||||
const char *MSBuildProvider::getPropertiesExtension() {
|
||||
return ".props";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline void outputConfiguration(std::ostream &project, const std::string &config, MSVC_Architecture arch) {
|
||||
project << "\t\t<ProjectConfiguration Include=\"" << config << "|" << getMSVCConfigName(arch) << "\">\n"
|
||||
<< "\t\t\t<Configuration>" << config << "</Configuration>\n"
|
||||
<< "\t\t\t<Platform>" << getMSVCConfigName(arch) << "</Platform>\n"
|
||||
<< "\t\t</ProjectConfiguration>\n";
|
||||
}
|
||||
|
||||
inline void outputConfigurationType(const BuildSetup &setup, std::ostream &project, const std::string &name, const std::string &config, MSVC_Architecture arch, const MSVCVersion &msvc) {
|
||||
project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << getMSVCConfigName(arch) << "'\" Label=\"Configuration\">\n";
|
||||
if (name == setup.projectName || setup.devTools || setup.tests) {
|
||||
project << "\t\t<ConfigurationType>Application</ConfigurationType>\n";
|
||||
} else {
|
||||
project << "\t\t<ConfigurationType>StaticLibrary</ConfigurationType>\n";
|
||||
}
|
||||
project << "\t\t<PlatformToolset>" << (config == "LLVM" ? msvc.toolsetLLVM : msvc.toolsetMSVC ) << "</PlatformToolset>\n";
|
||||
project << "\t\t<CharacterSet>" << (setup.useWindowsUnicode ? "Unicode" : "NotSet") << "</CharacterSet>\n";
|
||||
if (msvc.version >= 16 && config == "ASan") {
|
||||
project << "\t\t<EnableASAN>true</EnableASAN>\n";
|
||||
}
|
||||
project << "\t</PropertyGroup>\n";
|
||||
}
|
||||
|
||||
inline void outputProperties(const BuildSetup &setup, std::ostream &project, const std::string &config, MSVC_Architecture arch) {
|
||||
project << "\t<ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << getMSVCConfigName(arch) << "'\" Label=\"PropertySheets\">\n"
|
||||
<< "\t\t<Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n"
|
||||
<< "\t\t<Import Project=\"" << setup.projectDescription + '_' << config << getMSVCArchName(arch) << ".props" << "\" />\n"
|
||||
<< "\t</ImportGroup>\n";
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
void MSBuildProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
|
||||
std::ofstream project(projectFile.c_str());
|
||||
if (!project || !project.is_open()) {
|
||||
error("Could not open \"" + projectFile + "\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
project << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
<< "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << _msvcVersion.project << "\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
|
||||
<< "\t<ItemGroup Label=\"ProjectConfigurations\">\n";
|
||||
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
outputConfiguration(project, "Debug", *arch);
|
||||
outputConfiguration(project, "ASan", *arch);
|
||||
outputConfiguration(project, "LLVM", *arch);
|
||||
outputConfiguration(project, "Release", *arch);
|
||||
}
|
||||
project << "\t</ItemGroup>\n";
|
||||
|
||||
// Project name & Guid
|
||||
project << "\t<PropertyGroup Label=\"Globals\">\n"
|
||||
<< "\t\t<ProjectGuid>{" << uuid << "}</ProjectGuid>\n"
|
||||
<< "\t\t<RootNamespace>" << name << "</RootNamespace>\n"
|
||||
<< "\t\t<Keyword>Win32Proj</Keyword>\n"
|
||||
<< "\t\t<VCTargetsPath Condition=\"'$(VCTargetsPath" << _version << ")' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''\">$(VCTargetsPath" << _version << ")</VCTargetsPath>\n"
|
||||
<< "\t</PropertyGroup>\n";
|
||||
|
||||
// Shared configuration
|
||||
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n";
|
||||
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
outputConfigurationType(setup, project, name, "Release", *arch, _msvcVersion);
|
||||
outputConfigurationType(setup, project, name, "ASan", *arch, _msvcVersion);
|
||||
outputConfigurationType(setup, project, name, "LLVM", *arch, _msvcVersion);
|
||||
outputConfigurationType(setup, project, name, "Debug", *arch, _msvcVersion);
|
||||
}
|
||||
|
||||
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n"
|
||||
<< "\t<ImportGroup Label=\"ExtensionSettings\">\n"
|
||||
<< "\t</ImportGroup>\n";
|
||||
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
outputProperties(setup, project, "Release", *arch);
|
||||
outputProperties(setup, project, "ASan", *arch);
|
||||
outputProperties(setup, project, "LLVM", *arch);
|
||||
outputProperties(setup, project, "Debug", *arch);
|
||||
}
|
||||
|
||||
project << "\t<PropertyGroup Label=\"UserMacros\" />\n";
|
||||
|
||||
// Project-specific settings (asan uses debug properties)
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
BuildSetup archsetup = setup;
|
||||
std::map<MSVC_Architecture, StringList>::const_iterator disabled_features_it = _arch_disabled_features.find(*arch);
|
||||
if (disabled_features_it != _arch_disabled_features.end()) {
|
||||
for (StringList::const_iterator j = disabled_features_it->second.begin(); j != disabled_features_it->second.end(); ++j) {
|
||||
archsetup = removeFeatureFromSetup(archsetup, *j);
|
||||
}
|
||||
}
|
||||
outputProjectSettings(project, name, archsetup, false, *arch, "Debug");
|
||||
outputProjectSettings(project, name, archsetup, false, *arch, "ASan");
|
||||
outputProjectSettings(project, name, archsetup, false, *arch, "LLVM");
|
||||
outputProjectSettings(project, name, archsetup, true, *arch, "Release");
|
||||
}
|
||||
|
||||
// Files
|
||||
std::string modulePath;
|
||||
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
|
||||
modulePath = moduleDir.substr(setup.srcDir.size());
|
||||
if (!modulePath.empty() && modulePath.at(0) == '/')
|
||||
modulePath.erase(0, 1);
|
||||
}
|
||||
|
||||
if (!modulePath.empty())
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix + '/' + modulePath);
|
||||
else
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix);
|
||||
|
||||
// Output references for the main project
|
||||
if (name == setup.projectName)
|
||||
writeReferences(setup, project);
|
||||
|
||||
// Output auto-generated test runner
|
||||
if (setup.tests) {
|
||||
project << "\t<ItemGroup>\n";
|
||||
project << "\t\t<ClCompile Include=\"test/runner/test_runner.cpp\" />\n";
|
||||
project << "\t\t<ClCompile Include=\"" << setup.srcDir << "/test/system/null_osystem.cpp\" />\n";
|
||||
project << "\t\t<ClCompile Remove=\"" << setup.srcDir << "/backends/base-backend.cpp\" />\n"; // symbols are already defined in null_osystem.cpp
|
||||
project << "\t</ItemGroup>\n";
|
||||
}
|
||||
|
||||
// Visual Studio 2015 and up automatically import natvis files that are part of the project
|
||||
if (name == PROJECT_NAME && _version >= 14) {
|
||||
project << "\t<ItemGroup>\n";
|
||||
project << "\t\t<None Include=\"" << setup.srcDir << "/devtools/create_project/scripts/scummvm.natvis\" />\n";
|
||||
project << "\t</ItemGroup>\n";
|
||||
}
|
||||
|
||||
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n"
|
||||
"\t<ImportGroup Label=\"ExtensionTargets\">\n"
|
||||
"\t</ImportGroup>\n";
|
||||
|
||||
if (setup.tests) {
|
||||
// We override the normal target to ignore the exit code (this allows us to have a clean output and not message about the command exit code)
|
||||
project << "\t\t<Target Name=\"PostBuildEvent\">\n"
|
||||
<< "\t\t\t<Message Text=\"Description: Run tests\" />\n"
|
||||
<< "\t\t\t<Copy SourceFiles=\"" + setup.filePrefix + "/dists/engine-data/encoding.dat\" DestinationFolder=\"$(ProjectDir)test/engine-data\" SkipUnchangedFiles=\"true\" />\n"
|
||||
<< "\t\t\t<Exec Command=\"$(TargetPath)\" IgnoreExitCode=\"true\" />\n"
|
||||
<< "\t\t</Target>\n";
|
||||
}
|
||||
|
||||
project << "</Project>\n";
|
||||
|
||||
// Output filter file if necessary
|
||||
createFiltersFile(setup, name);
|
||||
}
|
||||
|
||||
void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::string &name) {
|
||||
// No filters => no need to create a filter file
|
||||
if (_filters.empty())
|
||||
return;
|
||||
|
||||
// Sort all list alphabetically
|
||||
_filters.sort();
|
||||
_compileFiles.sort();
|
||||
_includeFiles.sort();
|
||||
_otherFiles.sort();
|
||||
_resourceFiles.sort();
|
||||
_asmFiles.sort();
|
||||
|
||||
const std::string filtersFile = setup.outputDir + '/' + name + getProjectExtension() + ".filters";
|
||||
std::ofstream filters(filtersFile.c_str());
|
||||
if (!filters || !filters.is_open()) {
|
||||
error("Could not open \"" + filtersFile + "\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
filters << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
<< "<Project ToolsVersion=\"" << _msvcVersion.project << "\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
|
||||
|
||||
// Output the list of filters
|
||||
filters << "\t<ItemGroup>\n";
|
||||
for (std::list<std::string>::iterator filter = _filters.begin(); filter != _filters.end(); ++filter) {
|
||||
filters << "\t\t<Filter Include=\"" << *filter << "\">\n"
|
||||
<< "\t\t\t<UniqueIdentifier>" << createUUID() << "</UniqueIdentifier>\n"
|
||||
<< "\t\t</Filter>\n";
|
||||
}
|
||||
filters << "\t</ItemGroup>\n";
|
||||
|
||||
// Output files
|
||||
outputFilter(filters, _compileFiles, "ClCompile");
|
||||
outputFilter(filters, _includeFiles, "ClInclude");
|
||||
outputFilter(filters, _otherFiles, "None");
|
||||
outputFilter(filters, _resourceFiles, "ResourceCompile");
|
||||
outputFilter(filters, _asmFiles, "CustomBuild");
|
||||
|
||||
filters << "</Project>";
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputFilter(std::ostream &filters, const FileEntries &files, const std::string &action) {
|
||||
if (!files.empty()) {
|
||||
filters << "\t<ItemGroup>\n";
|
||||
for (FileEntries::const_iterator entry = files.begin(), end = files.end(); entry != end; ++entry) {
|
||||
if ((*entry).filter != "") {
|
||||
filters << "\t\t<" << action << " Include=\"" << (*entry).path << "\">\n"
|
||||
<< "\t\t\t<Filter>" << (*entry).filter << "</Filter>\n"
|
||||
<< "\t\t</" << action << ">\n";
|
||||
} else {
|
||||
filters << "\t\t<" << action << " Include=\"" << (*entry).path << "\" />\n";
|
||||
}
|
||||
}
|
||||
filters << "\t</ItemGroup>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::writeReferences(const BuildSetup &setup, std::ofstream &output) {
|
||||
output << "\t<ItemGroup>\n";
|
||||
|
||||
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
|
||||
output << "\t<ProjectReference Include=\"" << i->first << ".vcxproj\">\n"
|
||||
<< "\t\t<Project>{" << i->second << "}</Project>\n"
|
||||
<< "\t</ProjectReference>\n";
|
||||
}
|
||||
|
||||
output << "\t</ItemGroup>\n";
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration) {
|
||||
// Check for project-specific warnings:
|
||||
std::map<std::string, StringList>::iterator warningsIterator = _projectWarnings.find(name);
|
||||
bool enableLanguageExtensions = find(_enableLanguageExtensions.begin(), _enableLanguageExtensions.end(), name) != _enableLanguageExtensions.end();
|
||||
bool disableEditAndContinue = find(_disableEditAndContinue.begin(), _disableEditAndContinue.end(), name) != _disableEditAndContinue.end();
|
||||
|
||||
// Nothing to add here, move along!
|
||||
if (!setup.devTools && !setup.tests && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end())
|
||||
return;
|
||||
|
||||
std::string warnings = "";
|
||||
if (warningsIterator != _projectWarnings.end())
|
||||
for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
|
||||
warnings += *i + ';';
|
||||
|
||||
project << "\t<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='" << configuration << "|" << getMSVCConfigName(arch) << "'\">\n"
|
||||
<< "\t\t<ClCompile>\n";
|
||||
|
||||
// Language Extensions
|
||||
if (setup.devTools || setup.tests || name == setup.projectName || enableLanguageExtensions) {
|
||||
project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n";
|
||||
project << "\t\t\t<ConformanceMode>false</ConformanceMode>\n"; // Required for Windows SDK 8.1
|
||||
}
|
||||
|
||||
// Edit and Continue
|
||||
if ((name == setup.projectName || disableEditAndContinue) && !isRelease)
|
||||
project << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n";
|
||||
|
||||
// Warnings
|
||||
if (warningsIterator != _projectWarnings.end())
|
||||
project << "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n";
|
||||
|
||||
project << "\t\t</ClCompile>\n";
|
||||
|
||||
// Link configuration for main project
|
||||
if (name == setup.projectName || setup.devTools || setup.tests) {
|
||||
std::string libraries = outputLibraryDependencies(setup, isRelease);
|
||||
|
||||
// MSBuild uses ; for separators instead of spaces
|
||||
for (std::string::iterator i = libraries.begin(); i != libraries.end(); ++i) {
|
||||
if (*i == ' ') {
|
||||
*i = ';';
|
||||
}
|
||||
}
|
||||
|
||||
project << "\t\t<Link>\n"
|
||||
<< "\t\t\t<OutputFile>$(OutDir)" << ((setup.devTools || setup.tests) ? name : setup.projectName) << ".exe</OutputFile>\n"
|
||||
<< "\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n"
|
||||
<< "\t\t</Link>\n";
|
||||
|
||||
if (!setup.devTools && !setup.tests && setup.runBuildEvents) {
|
||||
project << "\t\t<PreBuildEvent>\n"
|
||||
<< "\t\t\t<Message>Generate revision</Message>\n"
|
||||
<< "\t\t\t<Command>" << getPreBuildEvent(setup) << "</Command>\n"
|
||||
<< "\t\t</PreBuildEvent>\n";
|
||||
|
||||
// Copy data files to the build folder
|
||||
project << "\t\t<PostBuildEvent>\n"
|
||||
<< "\t\t\t<Message>Copy data files to the build folder</Message>\n"
|
||||
<< "\t\t\t<Command>" << getPostBuildEvent(arch, setup, isRelease) << "</Command>\n"
|
||||
<< "\t\t</PostBuildEvent>\n";
|
||||
} else if (setup.tests) {
|
||||
project << "\t\t<PreBuildEvent>\n"
|
||||
<< "\t\t\t<Message>Generate runner.cpp</Message>\n"
|
||||
<< "\t\t\t<Command>" << getTestPreBuildEvent(setup) << "</Command>\n"
|
||||
<< "\t\t</PreBuildEvent>\n";
|
||||
}
|
||||
}
|
||||
|
||||
project << "\t</ItemDefinitionGroup>\n";
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstream &properties, MSVC_Architecture arch, const StringList &defines, const std::string &prefix) {
|
||||
|
||||
std::string warnings;
|
||||
for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i)
|
||||
warnings += *i + ';';
|
||||
|
||||
std::string warningsAsErrors;
|
||||
for (StringList::const_iterator i = _globalErrors.begin(); i != _globalErrors.end(); ++i)
|
||||
warningsAsErrors += "/we\"" + (*i) + "\" ";
|
||||
|
||||
std::string definesList;
|
||||
for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i)
|
||||
definesList += *i + ';';
|
||||
|
||||
// Add define to include revision header
|
||||
if (setup.runBuildEvents)
|
||||
definesList += REVISION_DEFINE ";";
|
||||
|
||||
std::string includeSDL = setup.getSDLName();
|
||||
|
||||
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
<< "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << _msvcVersion.project << "\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
|
||||
<< "\t<PropertyGroup>\n"
|
||||
<< "\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n"
|
||||
<< "\t\t<OutDir>$(Configuration)" << getMSVCArchName(arch) << "\\</OutDir>\n"
|
||||
<< "\t\t<IntDir>$(Configuration)" << getMSVCArchName(arch) << "\\$(ProjectName)\\</IntDir>\n";
|
||||
|
||||
if (_msvcVersion.version >= 17 && setup.useVcpkg)
|
||||
properties << "\t\t<VcpkgEnableManifest>true</VcpkgEnableManifest>\n";
|
||||
|
||||
properties << "\t</PropertyGroup>\n"
|
||||
<< "\t<ItemDefinitionGroup>\n"
|
||||
<< "\t\t<ClCompile>\n"
|
||||
<< "\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
|
||||
<< "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
|
||||
<< "\t\t\t<AdditionalIncludeDirectories>.;" << prefix << ";" << prefix << "\\engines;";
|
||||
if (setup.tests) {
|
||||
properties << prefix << "\\test\\cxxtest;";
|
||||
}
|
||||
// HACK to workaround SDL/SDL.h includes
|
||||
if (setup.useVcpkg) {
|
||||
properties << "$(_ZVcpkgCurrentInstalledDir)include\\" << includeSDL;
|
||||
}
|
||||
properties << "%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
|
||||
<< "\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
|
||||
<< "\t\t\t<ExceptionHandling>" << ((setup.devTools || setup.tests) ? "Sync" : "") << "</ExceptionHandling>\n";
|
||||
|
||||
#if NEEDS_RTTI
|
||||
properties << "\t\t\t<RuntimeTypeInfo>true</RuntimeTypeInfo>\n";
|
||||
#else
|
||||
properties << "\t\t\t<RuntimeTypeInfo>false</RuntimeTypeInfo>\n";
|
||||
#endif
|
||||
|
||||
// Print a bit more context for warnings, like modern GCC/Clang do
|
||||
if (_msvcVersion.version >= 15)
|
||||
properties << "\t\t\t<DiagnosticsFormat>Caret</DiagnosticsFormat>\n";
|
||||
|
||||
properties << "\t\t\t<WarningLevel>Level4</WarningLevel>\n"
|
||||
<< "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
|
||||
<< "\t\t\t<CompileAs>Default</CompileAs>\n"
|
||||
<< "\t\t\t<MultiProcessorCompilation>true</MultiProcessorCompilation>\n"
|
||||
<< "\t\t\t<ConformanceMode>true</ConformanceMode>\n"
|
||||
<< "\t\t\t<ObjectFileName>$(IntDir)dists\\msvc\\%(RelativeDir)</ObjectFileName>\n"
|
||||
<< "\t\t\t<AdditionalOptions>/utf-8 " << (_msvcVersion.version >= 15 ? "/Zc:__cplusplus " : "") << warningsAsErrors << "%(AdditionalOptions)</AdditionalOptions>\n"
|
||||
<< "\t\t</ClCompile>\n"
|
||||
<< "\t\t<Link>\n"
|
||||
<< "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n";
|
||||
// console subsystem is required for text-console, tools, and tests
|
||||
if (!setup.useWindowsSubsystem || setup.featureEnabled("text-console") || setup.devTools || setup.tests) {
|
||||
properties << "\t\t\t<SubSystem>Console</SubSystem>\n";
|
||||
} else {
|
||||
properties << "\t\t\t<SubSystem>Windows</SubSystem>\n";
|
||||
}
|
||||
|
||||
if (!setup.devTools && !setup.tests)
|
||||
properties << "\t\t\t<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n";
|
||||
|
||||
properties << "\t\t</Link>\n"
|
||||
<< "\t\t<ResourceCompile>\n"
|
||||
<< "\t\t\t<AdditionalIncludeDirectories>.;" << prefix << ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
|
||||
<< "\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
|
||||
<< "\t\t</ResourceCompile>\n"
|
||||
<< "\t</ItemDefinitionGroup>\n"
|
||||
<< "</Project>\n";
|
||||
|
||||
properties.flush();
|
||||
}
|
||||
|
||||
void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration) {
|
||||
std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_" + configuration + getMSVCArchName(arch) + getPropertiesExtension()).c_str());
|
||||
if (!properties || !properties.is_open()) {
|
||||
error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + configuration + getMSVCArchName(arch) + getPropertiesExtension() + "\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string includeDirsList;
|
||||
for (StringList::const_iterator i = setup.includeDirs.begin(); i != setup.includeDirs.end(); ++i)
|
||||
includeDirsList += convertPathToWin(*i) + ';';
|
||||
|
||||
std::string includeSDL = setup.getSDLName();
|
||||
|
||||
std::string libraryDirsList;
|
||||
for (StringList::const_iterator i = setup.libraryDirs.begin(); i != setup.libraryDirs.end(); ++i)
|
||||
libraryDirsList += convertPathToWin(*i) + ';';
|
||||
|
||||
std::string libsPath;
|
||||
if (setup.libsDir.empty())
|
||||
libsPath = "$(" LIBS_DEFINE ")";
|
||||
else
|
||||
libsPath = convertPathToWin(setup.libsDir);
|
||||
|
||||
std::string cfgPath = (isRelease ? "Release" : "Debug");
|
||||
|
||||
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
<< "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << _msvcVersion.project << "\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
|
||||
<< "\t<ImportGroup Label=\"PropertySheets\">\n"
|
||||
<< "\t\t<Import Project=\"" << setup.projectDescription << "_Global" << getMSVCArchName(arch) << ".props\" />\n"
|
||||
<< "\t</ImportGroup>\n"
|
||||
<< "\t<PropertyGroup>\n"
|
||||
<< "\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_" << configuration << getMSVCArchName(arch) << "</_PropertySheetDisplayName>\n"
|
||||
<< "\t\t<LinkIncremental>" << ((isRelease || configuration == "ASan") ? "false" : "true") << "</LinkIncremental>\n"
|
||||
<< "\t\t<GenerateManifest>false</GenerateManifest>\n";
|
||||
|
||||
if (!setup.useVcpkg) {
|
||||
properties << "\t\t<ExecutablePath>" << libsPath << "\\bin;" << libsPath << "\\bin\\" << getMSVCArchName(arch) << ";" << libsPath << "\\" << cfgPath << "\\bin;$(ExecutablePath)</ExecutablePath>\n"
|
||||
<< "\t\t<LibraryPath>" << libraryDirsList << libsPath << "\\lib\\" << getMSVCArchName(arch) << ";" << libsPath << "\\lib\\" << getMSVCArchName(arch) << "\\" << cfgPath << ";" << libsPath << "\\lib;" << libsPath << "\\" << cfgPath << "\\lib;$(LibraryPath)</LibraryPath>\n"
|
||||
<< "\t\t<IncludePath>" << includeDirsList << libsPath << "\\include;" << libsPath << "\\include\\" << includeSDL << ";$(IncludePath)</IncludePath>\n";
|
||||
} else {
|
||||
properties << "\t\t<VcpkgTriplet>" << getMSVCArchName(arch) << "-windows</VcpkgTriplet>\n";
|
||||
properties << "\t\t<VcpkgConfiguration>" << cfgPath << "</VcpkgConfiguration>\n";
|
||||
}
|
||||
|
||||
properties << "\t</PropertyGroup>\n"
|
||||
<< "\t<ItemDefinitionGroup>\n"
|
||||
<< "\t\t<ClCompile>\n";
|
||||
|
||||
if (isRelease) {
|
||||
properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n"
|
||||
<< "\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n"
|
||||
<< "\t\t\t<PreprocessorDefinitions>WIN32;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
|
||||
<< "\t\t\t<StringPooling>true</StringPooling>\n"
|
||||
<< "\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
|
||||
<< "\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
|
||||
<< "\t\t\t<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n"
|
||||
<< "\t\t\t<EnablePREfast>false</EnablePREfast>\n"
|
||||
<< "\t\t</ClCompile>\n"
|
||||
<< "\t\t<Lib>\n"
|
||||
<< "\t\t\t<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\n"
|
||||
<< "\t\t</Lib>\n"
|
||||
<< "\t\t<Link>\n"
|
||||
<< "\t\t\t<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>\n"
|
||||
<< "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
|
||||
<< "\t\t\t<SetChecksum>true</SetChecksum>\n";
|
||||
} else {
|
||||
properties << "\t\t\t<Optimization>Disabled</Optimization>\n"
|
||||
<< "\t\t\t<PreprocessorDefinitions>WIN32;" << (configuration == "LLVM" ? "_CRT_SECURE_NO_WARNINGS;" : "") << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
|
||||
<< "\t\t\t<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n"
|
||||
<< "\t\t\t<FunctionLevelLinking>true</FunctionLevelLinking>\n"
|
||||
<< "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n";
|
||||
if (configuration != "ASan") {
|
||||
properties << "\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n";
|
||||
}
|
||||
// Since MSVC 2015 Edit and Continue is supported for x86 and x86-64, but not for ARM.
|
||||
if (configuration != "ASan" && (arch == ARCH_X86 || (arch == ARCH_AMD64 && _version >= 14))) {
|
||||
properties << "\t\t\t<DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n";
|
||||
} else {
|
||||
properties << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n";
|
||||
}
|
||||
|
||||
if (configuration == "LLVM") {
|
||||
properties << "\t\t\t<AdditionalOptions>-Wno-microsoft -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder -Wpointer-arith -Wcast-qual -Wshadow -Wnon-virtual-dtor -Wwrite-strings -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants -Wno-nested-anon-types -Qunused-arguments %(AdditionalOptions)</AdditionalOptions>\n";
|
||||
}
|
||||
|
||||
properties << "\t\t</ClCompile>\n"
|
||||
<< "\t\t<Link>\n"
|
||||
<< "\t\t\t<GenerateDebugInformation>true</GenerateDebugInformation>\n"
|
||||
<< "\t\t\t<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n";
|
||||
}
|
||||
|
||||
properties << "\t\t</Link>\n"
|
||||
<< "\t</ItemDefinitionGroup>\n"
|
||||
<< "</Project>\n";
|
||||
|
||||
properties.flush();
|
||||
properties.close();
|
||||
}
|
||||
|
||||
bool hasEnding(std::string const &fullString, std::string const &ending) {
|
||||
if (fullString.length() > ending.length()) {
|
||||
return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputNasmCommand(std::ostream &projectFile, const std::string &config, const std::string &prefix) {
|
||||
projectFile << "\t\t\t<Command Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">nasm.exe -f win32 -g -o \"$(IntDir)" << prefix << "%(Filename).obj\" \"%(FullPath)\"</Command>\n"
|
||||
<< "\t\t\t<Outputs Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">$(IntDir)" << prefix << "%(Filename).obj;%(Outputs)</Outputs>\n";
|
||||
if (_version >= 15) {
|
||||
projectFile << "\t\t\t<OutputItemType Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">Object</OutputItemType>\n"
|
||||
<< "\t\t\t<BuildInParallel Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">true</BuildInParallel>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::insertPathIntoDirectory(FileNode &dir, const std::string &path) {
|
||||
size_t separatorLoc = path.find('\\');
|
||||
if (separatorLoc != std::string::npos) {
|
||||
// Inside of a subdirectory
|
||||
|
||||
std::string subdirName = path.substr(0, separatorLoc);
|
||||
|
||||
FileNode::NodeList::iterator dirIt = dir.children.begin();
|
||||
FileNode::NodeList::iterator dirItEnd = dir.children.end();
|
||||
while (dirIt != dirItEnd) {
|
||||
if ((*dirIt)->name == subdirName)
|
||||
break;
|
||||
|
||||
++dirIt;
|
||||
}
|
||||
|
||||
FileNode *dirNode = nullptr;
|
||||
if (dirIt == dirItEnd) {
|
||||
dirNode = new FileNode(subdirName);
|
||||
dir.children.push_back(dirNode);
|
||||
} else {
|
||||
dirNode = *dirIt;
|
||||
}
|
||||
|
||||
insertPathIntoDirectory(*dirNode, path.substr(separatorLoc + 1));
|
||||
} else {
|
||||
FileNode *fileNode = new FileNode(path);
|
||||
dir.children.push_back(fileNode);
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::createFileNodesFromPCHList(FileNode &dir, const std::string &pathBase, const StringList &pchCompileFiles) {
|
||||
for (StringList::const_iterator it = pchCompileFiles.begin(), itEnd = pchCompileFiles.end(); it != itEnd; ++it) {
|
||||
const std::string &pchPath = *it;
|
||||
|
||||
if (pchPath.size() > pathBase.size() && pchPath.substr(0, pathBase.size()) == pathBase) {
|
||||
std::string internalPath = pchPath.substr(pathBase.size());
|
||||
|
||||
insertPathIntoDirectory(dir, internalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
|
||||
// Reset lists
|
||||
_filters.clear();
|
||||
_compileFiles.clear();
|
||||
_includeFiles.clear();
|
||||
_otherFiles.clear();
|
||||
_resourceFiles.clear();
|
||||
_asmFiles.clear();
|
||||
|
||||
// Compute the list of files
|
||||
_filters.push_back(""); // init filters
|
||||
computeFileList(dir, objPrefix, filePrefix);
|
||||
_filters.pop_back(); // remove last empty filter
|
||||
|
||||
StringList pchCompileFiles;
|
||||
|
||||
// Output compile, include, other and resource files
|
||||
outputCompileFiles(projectFile, pchIncludeRoot, pchDirs, pchExclude, pchCompileFiles);
|
||||
outputFiles(projectFile, _includeFiles, "ClInclude");
|
||||
outputFiles(projectFile, _otherFiles, "None");
|
||||
outputFiles(projectFile, _resourceFiles, "ResourceCompile");
|
||||
|
||||
if (pchCompileFiles.size() > 0) {
|
||||
// Generate filters and additional compile files for PCH files
|
||||
FileNode pchDir(dir.name);
|
||||
createFileNodesFromPCHList(pchDir, convertPathToWin(dir.name) + '\\', pchCompileFiles);
|
||||
|
||||
StringList backupFilters = _filters;
|
||||
_filters.clear();
|
||||
|
||||
_filters.push_back(""); // init filters
|
||||
computeFileList(pchDir, objPrefix, filePrefix);
|
||||
_filters.pop_back(); // remove last empty filter
|
||||
|
||||
// Combine lists, removing duplicates
|
||||
for (StringList::const_iterator it = backupFilters.begin(), itEnd = backupFilters.end(); it != itEnd; ++it) {
|
||||
if (std::find(_filters.begin(), _filters.end(), *it) != _filters.end())
|
||||
_filters.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Output asm files
|
||||
if (!_asmFiles.empty()) {
|
||||
projectFile << "\t<ItemGroup>\n";
|
||||
for (std::list<FileEntry>::const_iterator entry = _asmFiles.begin(); entry != _asmFiles.end(); ++entry) {
|
||||
|
||||
projectFile << "\t\t<CustomBuild Include=\"" << (*entry).path << "\">\n"
|
||||
<< "\t\t\t<FileType>Document</FileType>\n";
|
||||
|
||||
outputNasmCommand(projectFile, "Debug", (*entry).prefix);
|
||||
outputNasmCommand(projectFile, "ASan", (*entry).prefix);
|
||||
outputNasmCommand(projectFile, "Release", (*entry).prefix);
|
||||
outputNasmCommand(projectFile, "LLVM", (*entry).prefix);
|
||||
|
||||
projectFile << "\t\t</CustomBuild>\n";
|
||||
}
|
||||
projectFile << "\t</ItemGroup>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputFiles(std::ostream &projectFile, const FileEntries &files, const std::string &action) {
|
||||
if (!files.empty()) {
|
||||
projectFile << "\t<ItemGroup>\n";
|
||||
for (FileEntries::const_iterator entry = files.begin(), end = files.end(); entry != end; ++entry) {
|
||||
projectFile << "\t\t<" << action << " Include=\"" << (*entry).path << "\" />\n";
|
||||
}
|
||||
projectFile << "\t</ItemGroup>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::outputCompileFiles(std::ostream &projectFile, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, StringList &outPCHFiles) {
|
||||
const FileEntries &files = _compileFiles;
|
||||
|
||||
const bool hasPCH = (pchDirs.size() > 0);
|
||||
|
||||
std::string pchIncludeRootWin;
|
||||
StringList pchDirsWin;
|
||||
StringList pchExcludeWin;
|
||||
|
||||
if (hasPCH) {
|
||||
pchIncludeRootWin = convertPathToWin(pchIncludeRoot);
|
||||
|
||||
// Convert PCH paths to Win
|
||||
for (StringList::const_iterator entry = pchDirs.begin(), end = pchDirs.end(); entry != end; ++entry) {
|
||||
std::string convertedPath = convertPathToWin(*entry);
|
||||
if (convertedPath.size() < pchIncludeRootWin.size() || convertedPath.substr(0, pchIncludeRootWin.size()) != pchIncludeRootWin) {
|
||||
error("PCH path '" + convertedPath + "' wasn't located under PCH include root '" + pchIncludeRootWin + "'");
|
||||
}
|
||||
|
||||
pchDirsWin.push_back(convertPathToWin(*entry));
|
||||
}
|
||||
for (StringList::const_iterator entry = pchExclude.begin(), end = pchExclude.end(); entry != end; ++entry) {
|
||||
const std::string path = *entry;
|
||||
|
||||
if (path.size() >= 2 && path[path.size() - 1] == 'o' && path[path.size() - 2] == '.')
|
||||
pchExcludeWin.push_back(convertPathToWin(path.substr(0, path.size() - 2)));
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, PCHInfo> pchMap;
|
||||
|
||||
if (!files.empty()) {
|
||||
projectFile << "\t<ItemGroup>\n";
|
||||
for (FileEntries::const_iterator entry = files.begin(), end = files.end(); entry != end; ++entry) {
|
||||
std::string pchIncludePath, pchFilePath, pchFileName;
|
||||
|
||||
bool fileHasPCH = false;
|
||||
if (hasPCH)
|
||||
fileHasPCH = calculatePchPaths(entry->path, pchIncludeRootWin, pchDirsWin, pchExcludeWin, '\\', pchIncludePath, pchFilePath, pchFileName);
|
||||
|
||||
if (fileHasPCH) {
|
||||
std::string pchOutputFileName = "$(IntDir)dists\\msvc\\%(RelativeDir)" + pchFileName.substr(0, pchFileName.size() - 2) + ".pch";
|
||||
|
||||
PCHInfo &pchInfo = pchMap[pchFilePath];
|
||||
pchInfo.file = pchIncludePath;
|
||||
pchInfo.outputFile = pchOutputFileName;
|
||||
|
||||
projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\">\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeader>Use</PrecompiledHeader>\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeaderFile>" << pchIncludePath << "</PrecompiledHeaderFile>\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeaderOutputFile>" << pchOutputFileName << "</PrecompiledHeaderOutputFile>\n";
|
||||
projectFile << "\t\t</ClCompile>\n";
|
||||
} else {
|
||||
projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\" />\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Flush PCH files
|
||||
for (std::map<std::string, PCHInfo>::const_iterator pchIt = pchMap.begin(), pchItEnd = pchMap.end(); pchIt != pchItEnd; ++pchIt) {
|
||||
const PCHInfo &pchInfo = pchIt->second;
|
||||
|
||||
const std::string &filePath = pchIt->first;
|
||||
assert(filePath.size() >= 2 && filePath.substr(filePath.size() - 2) == ".h");
|
||||
|
||||
std::string cppFilePath = filePath.substr(0, filePath.size() - 2) + ".cpp";
|
||||
|
||||
std::string expectedContents = "/* This file is automatically generated by create_project */\n"
|
||||
"/* DO NOT EDIT MANUALLY */\n"
|
||||
"#include \"" + pchInfo.file + "\"\n";
|
||||
|
||||
// Try to avoid touching the generated .cpp if it's identical to the expected output.
|
||||
// If we touch the file, then every file that includes PCH needs to be recompiled.
|
||||
std::ifstream pchInputFile(cppFilePath.c_str());
|
||||
bool needToEmit = true;
|
||||
if (pchInputFile && pchInputFile.is_open()) {
|
||||
std::string fileContents;
|
||||
for (;;) {
|
||||
char buffer[1024];
|
||||
size_t numRead = sizeof(buffer) - 1;
|
||||
pchInputFile.read(buffer, numRead);
|
||||
|
||||
buffer[pchInputFile.gcount()] = '\0';
|
||||
|
||||
fileContents += buffer;
|
||||
|
||||
if (pchInputFile.eof() || pchInputFile.fail())
|
||||
break;
|
||||
|
||||
if (fileContents.size() > expectedContents.size())
|
||||
break;
|
||||
}
|
||||
|
||||
needToEmit = (fileContents != expectedContents);
|
||||
pchInputFile.close();
|
||||
}
|
||||
|
||||
if (needToEmit) {
|
||||
std::ofstream pchOutputFile(cppFilePath.c_str());
|
||||
if (!pchOutputFile || !pchOutputFile.is_open()) {
|
||||
error("Could not open \"" + cppFilePath + "\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
pchOutputFile << expectedContents;
|
||||
pchOutputFile.close();
|
||||
}
|
||||
|
||||
projectFile << "\t\t<ClCompile Include=\"" << cppFilePath << "\">\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeader>Create</PrecompiledHeader>\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeaderFile>" << pchInfo.file << "</PrecompiledHeaderFile>\n";
|
||||
projectFile << "\t\t\t<PrecompiledHeaderOutputFile>" << pchInfo.outputFile << "</PrecompiledHeaderOutputFile>\n";
|
||||
projectFile << "\t\t</ClCompile>\n";
|
||||
|
||||
outPCHFiles.push_back(cppFilePath);
|
||||
}
|
||||
|
||||
projectFile << "\t</ItemGroup>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void MSBuildProvider::computeFileList(const FileNode &dir, const std::string &objPrefix, const std::string &filePrefix) {
|
||||
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
|
||||
const FileNode *node = *i;
|
||||
|
||||
if (!node->children.empty()) {
|
||||
// Update filter
|
||||
std::string _currentFilter = _filters.back();
|
||||
_filters.back().append((_filters.back() == "" ? "" : "\\") + node->name);
|
||||
|
||||
computeFileList(*node, objPrefix + node->name + '_', filePrefix + node->name + '/');
|
||||
|
||||
// Reset filter
|
||||
_filters.push_back(_currentFilter);
|
||||
} else {
|
||||
// Filter files by extension
|
||||
std::string name, ext;
|
||||
splitFilename(node->name, name, ext);
|
||||
|
||||
FileEntry entry;
|
||||
entry.name = name;
|
||||
entry.path = convertPathToWin(filePrefix + node->name);
|
||||
entry.filter = _filters.back();
|
||||
entry.prefix = objPrefix;
|
||||
|
||||
if (ext == "cpp" || ext == "c")
|
||||
_compileFiles.push_back(entry);
|
||||
else if (ext == "h")
|
||||
_includeFiles.push_back(entry);
|
||||
else if (ext == "rc")
|
||||
_resourceFiles.push_back(entry);
|
||||
else if (ext == "asm")
|
||||
_asmFiles.push_back(entry);
|
||||
else
|
||||
_otherFiles.push_back(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace CreateProjectTool
|
||||
92
devtools/create_project/msbuild.h
Normal file
92
devtools/create_project/msbuild.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_MSBUILD_H
|
||||
#define TOOLS_CREATE_PROJECT_MSBUILD_H
|
||||
|
||||
#include "msvc.h"
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
class MSBuildProvider final : public MSVCProvider {
|
||||
public:
|
||||
MSBuildProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors, const int version, const MSVCVersion &msvc);
|
||||
|
||||
protected:
|
||||
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) override;
|
||||
|
||||
void outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration);
|
||||
|
||||
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) override;
|
||||
|
||||
void writeReferences(const BuildSetup &setup, std::ofstream &output) override;
|
||||
|
||||
void outputGlobalPropFile(const BuildSetup &setup, std::ofstream &properties, MSVC_Architecture arch, const StringList &defines, const std::string &prefix) override;
|
||||
|
||||
void createBuildProp(const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration) override;
|
||||
|
||||
const char *getProjectExtension() override;
|
||||
const char *getPropertiesExtension() override;
|
||||
|
||||
private:
|
||||
struct FileEntry {
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::string filter;
|
||||
std::string prefix;
|
||||
|
||||
bool operator<(const FileEntry &rhs) const {
|
||||
return path.compare(rhs.path) == -1; // Not exactly right for alphabetical order, but good enough
|
||||
}
|
||||
};
|
||||
typedef std::list<FileEntry> FileEntries;
|
||||
|
||||
struct PCHInfo {
|
||||
std::string file;
|
||||
std::string outputFile;
|
||||
};
|
||||
|
||||
std::list<std::string> _filters; // list of filters (we need to create a GUID for each filter id)
|
||||
FileEntries _compileFiles;
|
||||
FileEntries _includeFiles;
|
||||
FileEntries _otherFiles;
|
||||
FileEntries _asmFiles;
|
||||
FileEntries _resourceFiles;
|
||||
|
||||
void computeFileList(const FileNode &dir, const std::string &objPrefix, const std::string &filePrefix);
|
||||
void createFiltersFile(const BuildSetup &setup, const std::string &name);
|
||||
|
||||
void outputFilter(std::ostream &filters, const FileEntries &files, const std::string &action);
|
||||
void outputFiles(std::ostream &projectFile, const FileEntries &files, const std::string &action);
|
||||
void outputCompileFiles(std::ostream &projectFile, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, StringList &outPCHFiles);
|
||||
|
||||
void outputNasmCommand(std::ostream &projectFile, const std::string &config, const std::string &prefix);
|
||||
|
||||
static void createFileNodesFromPCHList(FileNode &dir, const std::string &pathBase, const StringList &pchCompileFiles);
|
||||
static void insertPathIntoDirectory(FileNode &dir, const std::string &path);
|
||||
};
|
||||
|
||||
} // namespace CreateProjectTool
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_MSBUILD_H
|
||||
368
devtools/create_project/msvc.cpp
Normal file
368
devtools/create_project/msvc.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "msvc.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MSVC Provider (Base class)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MSVCProvider::MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors, const int version, const MSVCVersion &msvc)
|
||||
: ProjectProvider(global_warnings, project_warnings, global_errors), _version(version), _msvcVersion(msvc) {
|
||||
|
||||
_enableLanguageExtensions = tokenize(ENABLE_LANGUAGE_EXTENSIONS, ',');
|
||||
_disableEditAndContinue = tokenize(DISABLE_EDIT_AND_CONTINUE, ',');
|
||||
|
||||
// NASM not supported for Windows on AMD64 target
|
||||
StringList amd64_disabled_features;
|
||||
amd64_disabled_features.push_back("nasm");
|
||||
_arch_disabled_features[ARCH_AMD64] = amd64_disabled_features;
|
||||
// NASM not supported for WoA target
|
||||
StringList arm64_disabled_features;
|
||||
arm64_disabled_features.push_back("nasm");
|
||||
_arch_disabled_features[ARCH_ARM64] = arm64_disabled_features;
|
||||
}
|
||||
|
||||
std::string MSVCProvider::getLibraryFromFeature(const char *feature, const BuildSetup &setup, bool isRelease) const {
|
||||
static const MSVCLibrary s_libraries[] = {
|
||||
// Libraries
|
||||
{ "sdl", "SDL.lib", "SDLd.lib", kSDLVersion1, "winmm.lib imm32.lib version.lib setupapi.lib" },
|
||||
{ "sdl", "SDL2.lib", "SDL2d.lib", kSDLVersion2, "winmm.lib imm32.lib version.lib setupapi.lib" },
|
||||
{ "sdl", "SDL3.lib", "SDL3d.lib", kSDLVersion3, "winmm.lib imm32.lib version.lib setupapi.lib" },
|
||||
{ "zlib", "zlib.lib", "zlibd.lib", kSDLVersionAny, nullptr },
|
||||
{ "mad", "mad.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "fribidi", "fribidi.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "ogg", "ogg.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "vorbis", "vorbis.lib vorbisfile.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "tremor", "vorbisidec.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "flac", "FLAC.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "png", "libpng16.lib", "libpng16d.lib", kSDLVersionAny, nullptr },
|
||||
{ "gif", "gif.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "faad", "faad.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "mikmod", "mikmod.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "openmpt", "openmpt.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "mpeg2", "mpeg2.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "theoradec", "theora.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "vpx", "vpx.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "freetype2", "freetype.lib", "freetyped.lib", kSDLVersionAny, nullptr },
|
||||
{ "jpeg", "jpeg.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{"fluidsynth", "fluidsynth.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "fluidlite", "fluidlite.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "libcurl", "libcurl.lib", "libcurl-d.lib", kSDLVersionAny, "ws2_32.lib wldap32.lib crypt32.lib normaliz.lib" },
|
||||
{ "sdlnet", "SDL_net.lib", nullptr, kSDLVersion1, "iphlpapi.lib" },
|
||||
{ "sdlnet", "SDL2_net.lib", "SDL2_netd.lib", kSDLVersion2, "iphlpapi.lib" },
|
||||
{ "sdlnet", "SDL3_net.lib", "SDL3_netd.lib", kSDLVersion3, "iphlpapi.lib" },
|
||||
{ "discord", "discord-rpc.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "retrowave", "RetroWave.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "a52", "a52.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "mpc", "libmpcdec.lib", "libmpcdec_d.lib", kSDLVersionAny, nullptr },
|
||||
// Feature flags with library dependencies
|
||||
{ "updates", "WinSparkle.lib", nullptr, kSDLVersionAny, nullptr },
|
||||
{ "tts", nullptr, nullptr, kSDLVersionAny, "sapi.lib" },
|
||||
{ "opengl", nullptr, nullptr, kSDLVersionAny, nullptr },
|
||||
{ "enet", nullptr, nullptr, kSDLVersionAny, "winmm.lib ws2_32.lib" }
|
||||
};
|
||||
|
||||
const MSVCLibrary *library = nullptr;
|
||||
for (unsigned int i = 0; i < sizeof(s_libraries) / sizeof(s_libraries[0]); i++) {
|
||||
if (std::strcmp(feature, s_libraries[i].feature) == 0 &&
|
||||
((s_libraries[i].sdl == kSDLVersionAny) ||
|
||||
(s_libraries[i].sdl == setup.useSDL))) {
|
||||
library = &s_libraries[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string libs;
|
||||
if (library) {
|
||||
// Dependencies come first
|
||||
if (library->depends) {
|
||||
libs += library->depends;
|
||||
libs += " ";
|
||||
}
|
||||
|
||||
// Vcpkg already adds the libs
|
||||
if (!setup.useVcpkg) {
|
||||
const char *basename = library->release;
|
||||
// Debug name takes priority
|
||||
if (!isRelease && library->debug) {
|
||||
basename = library->debug;
|
||||
}
|
||||
if (basename) {
|
||||
libs += basename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return libs;
|
||||
}
|
||||
|
||||
std::string MSVCProvider::outputLibraryDependencies(const BuildSetup &setup, bool isRelease) const {
|
||||
std::string libs;
|
||||
|
||||
// SDL is always enabled
|
||||
libs += getLibraryFromFeature("sdl", setup, isRelease);
|
||||
libs += " ";
|
||||
for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
|
||||
if (i->enable) {
|
||||
std::string lib = getLibraryFromFeature(i->name, setup, isRelease);
|
||||
if (!lib.empty())
|
||||
libs += lib + " ";
|
||||
}
|
||||
}
|
||||
|
||||
return libs;
|
||||
}
|
||||
|
||||
void MSVCProvider::createWorkspace(const BuildSetup &setup) {
|
||||
if (setup.useSlnx)
|
||||
createWorkspaceXml(setup);
|
||||
else
|
||||
createWorkspaceClassic(setup);
|
||||
}
|
||||
|
||||
void MSVCProvider::createWorkspaceClassic(const BuildSetup &setup) {
|
||||
UUIDMap::const_iterator svmUUID = _allProjUuidMap.find(setup.projectName);
|
||||
if (svmUUID == _allProjUuidMap.end())
|
||||
error("No UUID for \"" + setup.projectName + "\" project created");
|
||||
|
||||
const std::string svmProjectUUID = svmUUID->second;
|
||||
assert(!svmProjectUUID.empty());
|
||||
|
||||
std::string solutionUUID = createUUID(setup.projectName + ".sln");
|
||||
|
||||
std::ofstream solution((setup.outputDir + '/' + setup.projectName + ".sln").c_str());
|
||||
if (!solution || !solution.is_open()) {
|
||||
error("Could not open \"" + setup.outputDir + '/' + setup.projectName + ".sln\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
solution << "Microsoft Visual Studio Solution File, Format Version " << _msvcVersion.solutionFormat << "\n";
|
||||
solution << "# Visual Studio " << _msvcVersion.solutionVersion << "\n";
|
||||
if (_version >= 12) {
|
||||
solution << "VisualStudioVersion = " << _msvcVersion.project << ".0.0\n";
|
||||
solution << "MinimumVisualStudioVersion = 10.0.40219.1\n";
|
||||
}
|
||||
|
||||
// Write main project
|
||||
if (!setup.devTools) {
|
||||
solution << "Project(\"{" << solutionUUID << "}\") = \"" << setup.projectName << "\", \"" << setup.projectName << getProjectExtension() << "\", \"{" << svmProjectUUID << "}\"\n";
|
||||
|
||||
// Project dependencies are moved to vcxproj files in Visual Studio 2010
|
||||
if (_version < 10)
|
||||
writeReferences(setup, solution);
|
||||
|
||||
solution << "EndProject\n";
|
||||
}
|
||||
|
||||
// Note we assume that the UUID map only includes UUIDs for enabled engines!
|
||||
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
|
||||
solution << "Project(\"{" << solutionUUID << "}\") = \"" << i->first << "\", \"" << i->first << getProjectExtension() << "\", \"{" << i->second << "}\"\n"
|
||||
<< "EndProject\n";
|
||||
}
|
||||
|
||||
solution << "Global\n"
|
||||
"\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
|
||||
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
solution << "\t\tDebug|" << getMSVCConfigName(*arch) << " = Debug|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\tASan|" << getMSVCConfigName(*arch) << " = ASan|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\tLLVM|" << getMSVCConfigName(*arch) << " = LLVM|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\tRelease|" << getMSVCConfigName(*arch) << " = Release|" << getMSVCConfigName(*arch) << "\n";
|
||||
}
|
||||
|
||||
solution << "\tEndGlobalSection\n"
|
||||
"\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
|
||||
|
||||
for (UUIDMap::const_iterator i = _allProjUuidMap.begin(); i != _allProjUuidMap.end(); ++i) {
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
solution << "\t\t{" << i->second << "}.Debug|" << getMSVCConfigName(*arch) << ".ActiveCfg = Debug|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.Debug|" << getMSVCConfigName(*arch) << ".Build.0 = Debug|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.ASan|" << getMSVCConfigName(*arch) << ".ActiveCfg = ASan|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.ASan|" << getMSVCConfigName(*arch) << ".Build.0 = ASan|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.LLVM|" << getMSVCConfigName(*arch) << ".ActiveCfg = LLVM|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.LLVM|" << getMSVCConfigName(*arch) << ".Build.0 = LLVM|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.Release|" << getMSVCConfigName(*arch) << ".ActiveCfg = Release|" << getMSVCConfigName(*arch) << "\n"
|
||||
<< "\t\t{" << i->second << "}.Release|" << getMSVCConfigName(*arch) << ".Build.0 = Release|" << getMSVCConfigName(*arch) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
solution << "\tEndGlobalSection\n"
|
||||
<< "\tGlobalSection(SolutionProperties) = preSolution\n"
|
||||
<< "\t\tHideSolutionNode = FALSE\n"
|
||||
<< "\tEndGlobalSection\n"
|
||||
<< "EndGlobal\n";
|
||||
}
|
||||
|
||||
void MSVCProvider::createWorkspaceXml(const BuildSetup &setup) {
|
||||
const auto svmUUID = _allProjUuidMap.find(setup.projectName);
|
||||
if (svmUUID == _allProjUuidMap.end())
|
||||
error("No UUID for \"" + setup.projectName + "\" project created");
|
||||
|
||||
const std::string &svmProjectUUID = svmUUID->second;
|
||||
assert(!svmProjectUUID.empty());
|
||||
|
||||
std::ofstream solution((setup.outputDir + '/' + setup.projectName + ".slnx").c_str());
|
||||
if (!solution || !solution.is_open()) {
|
||||
error("Could not open \"" + setup.outputDir + '/' + setup.projectName + ".slnx\" for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
solution << "<Solution>\n";
|
||||
|
||||
solution << "\t<Configurations>\n";
|
||||
|
||||
solution << "\t\t<BuildType Name=\"ASan\" />\n";
|
||||
solution << "\t\t<BuildType Name=\"Debug\" />\n";
|
||||
solution << "\t\t<BuildType Name=\"LLVM\" />\n";
|
||||
solution << "\t\t<BuildType Name=\"Release\" />\n";
|
||||
|
||||
for (const auto &arch : _archs) {
|
||||
solution << "\t\t<Platform Name=\"" << getMSVCConfigName(arch) << "\" />\n";
|
||||
}
|
||||
solution << "\t</Configurations>\n";
|
||||
|
||||
// Write main project
|
||||
if (!setup.devTools) {
|
||||
solution << "\t<Project Path=\"" << setup.projectName << getProjectExtension()
|
||||
<< "\" Id=\"" << svmProjectUUID << "\" "
|
||||
<< " DefaultStartup=\"true\"" /* DefaultStartup has no effect in VS2022, needs VS2026+ */
|
||||
<< " />\n";
|
||||
}
|
||||
|
||||
for (const auto &engineUuid : _engineUuidMap) {
|
||||
solution << "\t<Project Path=\"" << engineUuid.first << getProjectExtension()
|
||||
<< "\" Id=\"" << engineUuid.second
|
||||
<< "\" />\n";
|
||||
}
|
||||
|
||||
solution << "</Solution>\n";
|
||||
}
|
||||
|
||||
void MSVCProvider::createOtherBuildFiles(const BuildSetup &setup) {
|
||||
// Create the global property file
|
||||
createGlobalProp(setup);
|
||||
|
||||
// Create the configuration property files (for Debug and Release with 32 and 64bits versions)
|
||||
// Note: we use the debug properties for the asan configuration
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
createBuildProp(setup, true, *arch, "Release");
|
||||
createBuildProp(setup, false, *arch, "Debug");
|
||||
createBuildProp(setup, false, *arch, "ASan");
|
||||
createBuildProp(setup, false, *arch, "LLVM");
|
||||
}
|
||||
}
|
||||
|
||||
void MSVCProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
|
||||
includeList.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
|
||||
includeList.push_back(setup.srcDir + "/dists/" + setup.projectName + ".rc");
|
||||
}
|
||||
|
||||
void MSVCProvider::createGlobalProp(const BuildSetup &setup) {
|
||||
for (std::list<MSVC_Architecture>::const_iterator arch = _archs.begin(); arch != _archs.end(); ++arch) {
|
||||
std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_Global" + getMSVCArchName(*arch) + getPropertiesExtension()).c_str());
|
||||
if (!properties)
|
||||
error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_Global" + getMSVCArchName(*arch) + getPropertiesExtension() + "\" for writing");
|
||||
|
||||
BuildSetup archSetup = setup;
|
||||
std::map<MSVC_Architecture, StringList>::const_iterator arch_disabled_features_it = _arch_disabled_features.find(*arch);
|
||||
if (arch_disabled_features_it != _arch_disabled_features.end()) {
|
||||
for (StringList::const_iterator feature = arch_disabled_features_it->second.begin(); feature != arch_disabled_features_it->second.end(); ++feature) {
|
||||
archSetup = removeFeatureFromSetup(archSetup, *feature);
|
||||
}
|
||||
}
|
||||
|
||||
outputGlobalPropFile(archSetup, properties, *arch, archSetup.defines, convertPathToWin(archSetup.filePrefix));
|
||||
properties.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string MSVCProvider::getPreBuildEvent(const BuildSetup &setup) const {
|
||||
std::string cmdLine = "";
|
||||
|
||||
cmdLine = "@echo off\n"
|
||||
"echo Executing Pre-Build script...\n"
|
||||
"echo.\n"
|
||||
"@call "$(SolutionDir)" + setup.filePrefix + "/devtools/create_project/scripts/prebuild.cmd" "$(SolutionDir)/" + setup.filePrefix + "" "$(SolutionDir)"\n"
|
||||
"EXIT /B0";
|
||||
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
std::string MSVCProvider::getTestPreBuildEvent(const BuildSetup &setup) const {
|
||||
// Build list of folders containing tests
|
||||
std::string target = "";
|
||||
|
||||
for (StringList::const_iterator it = setup.testDirs.begin(); it != setup.testDirs.end(); ++it)
|
||||
target += " $(SolutionDir)" + *it + "*.h";
|
||||
|
||||
std::string cmdLine = "";
|
||||
cmdLine = "if not exist \"$(SolutionDir)test\\runner\" mkdir \"$(SolutionDir)test\\runner\"\n"
|
||||
"python3 "$(SolutionDir)" + setup.filePrefix + "/test/cxxtest/cxxtestgen.py" --runner=ParenPrinter --no-std --no-eh -o "$(SolutionDir)test/runner/test_runner.cpp"" + target;
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
std::string MSVCProvider::getPostBuildEvent(MSVC_Architecture arch, const BuildSetup &setup, bool isRelease) const {
|
||||
std::string cmdLine = "";
|
||||
|
||||
cmdLine = "@echo off\n"
|
||||
"echo Executing Post-Build script...\n"
|
||||
"echo.\n"
|
||||
"@call "$(SolutionDir)" + setup.filePrefix + "/devtools/create_project/scripts/postbuild.cmd" "$(SolutionDir)" + setup.filePrefix + "" "$(OutDir)" ";
|
||||
|
||||
cmdLine += setup.getSDLName();
|
||||
|
||||
if (setup.useVcpkg) {
|
||||
cmdLine += " "$(_ZVcpkgCurrentInstalledDir)";
|
||||
if (!isRelease) {
|
||||
cmdLine += "debug/";
|
||||
}
|
||||
cmdLine += "bin/" ";
|
||||
} else {
|
||||
std::string libsPath;
|
||||
if (setup.libsDir.empty())
|
||||
libsPath = "%" LIBS_DEFINE "%";
|
||||
else
|
||||
libsPath = convertPathToWin(setup.libsDir);
|
||||
|
||||
cmdLine += " "";
|
||||
cmdLine += libsPath;
|
||||
cmdLine += "/lib/";
|
||||
cmdLine += getMSVCArchName(arch);
|
||||
cmdLine += "/$(Configuration)" ";
|
||||
}
|
||||
|
||||
// Specify if installer needs to be built or not
|
||||
cmdLine += (setup.createInstaller ? "1" : "0");
|
||||
|
||||
cmdLine += "\n"
|
||||
"EXIT /B0";
|
||||
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
} // namespace CreateProjectTool
|
||||
129
devtools/create_project/msvc.h
Normal file
129
devtools/create_project/msvc.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_MSVC_H
|
||||
#define TOOLS_CREATE_PROJECT_MSVC_H
|
||||
|
||||
#include "create_project.h"
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
class MSVCProvider : public ProjectProvider {
|
||||
public:
|
||||
MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors, const int version, const MSVCVersion &msvcVersion);
|
||||
|
||||
protected:
|
||||
const int _version;
|
||||
const MSVCVersion _msvcVersion;
|
||||
|
||||
StringList _enableLanguageExtensions;
|
||||
StringList _disableEditAndContinue;
|
||||
|
||||
std::list<MSVC_Architecture> _archs;
|
||||
std::map<MSVC_Architecture, StringList> _arch_disabled_features;
|
||||
|
||||
/**
|
||||
* MSVC properties for a library required by a feature
|
||||
*/
|
||||
struct MSVCLibrary {
|
||||
const char *feature; ///< Feature ID.
|
||||
const char *release; ///< Filename of the Release build of the library.
|
||||
const char *debug; ///< Filename of the Debug build of the library.
|
||||
SDLVersion sdl; ///< Required SDL version.
|
||||
const char *depends; ///< Win32 libs this library must be linked against.
|
||||
};
|
||||
|
||||
std::string getLibraryFromFeature(const char *feature, const BuildSetup &setup, bool isRelease) const;
|
||||
std::string outputLibraryDependencies(const BuildSetup &setup, bool isRelease) const;
|
||||
|
||||
void createWorkspace(const BuildSetup &setup) override;
|
||||
void createWorkspaceClassic(const BuildSetup &setup);
|
||||
void createWorkspaceXml(const BuildSetup &setup);
|
||||
|
||||
void createOtherBuildFiles(const BuildSetup &setup) override;
|
||||
|
||||
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) override;
|
||||
|
||||
/**
|
||||
* Create the global project properties.
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
void createGlobalProp(const BuildSetup &setup);
|
||||
|
||||
/**
|
||||
* Outputs a property file based on the input parameters.
|
||||
*
|
||||
* It can be easily used to create different global properties files
|
||||
* for a 64 bit and a 32 bit version. It will also take care that the
|
||||
* two platform configurations will output their files into different
|
||||
* directories.
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
* @param properties File stream in which to write the property settings.
|
||||
* @param arch Target architecture
|
||||
* @param defines Defines the platform needs to have set.
|
||||
* @param prefix File prefix, used to add additional include paths.
|
||||
*/
|
||||
virtual void outputGlobalPropFile(const BuildSetup &setup, std::ofstream &properties, MSVC_Architecture arch, const StringList &defines, const std::string &prefix) = 0;
|
||||
|
||||
/**
|
||||
* Generates the project properties for debug and release settings.
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
* @param isRelease Type of property file
|
||||
* @param arch Target architecture
|
||||
* @param configuration Name of property file
|
||||
*/
|
||||
virtual void createBuildProp(const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration) = 0;
|
||||
|
||||
/**
|
||||
* Get the file extension for property files
|
||||
*/
|
||||
virtual const char *getPropertiesExtension() = 0;
|
||||
|
||||
/**
|
||||
* Get the command line for the revision tool (shared between all Visual Studio based providers)
|
||||
*/
|
||||
std::string getPreBuildEvent(const BuildSetup &setup) const;
|
||||
|
||||
/**
|
||||
* Get the command line for the test generator
|
||||
*
|
||||
* @param setup Description of the desired build setup.
|
||||
*/
|
||||
std::string getTestPreBuildEvent(const BuildSetup &setup) const;
|
||||
|
||||
/**
|
||||
* Get the command line for copying data files to the build directory.
|
||||
*
|
||||
* @param arch Target architecture
|
||||
* @param setup Description of the desired build setup.
|
||||
* @param isRelease Type of build file
|
||||
*
|
||||
* @return The post build event.
|
||||
*/
|
||||
std::string getPostBuildEvent(MSVC_Architecture arch, const BuildSetup &setup, bool isRelease) const;
|
||||
};
|
||||
|
||||
} // namespace CreateProjectTool
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_MSVC_H
|
||||
182
devtools/create_project/scripts/installer.vbs
Normal file
182
devtools/create_project/scripts/installer.vbs
Normal file
@@ -0,0 +1,182 @@
|
||||
'
|
||||
' ScummVM - Graphic Adventure Engine
|
||||
'
|
||||
' ScummVM is the legal property of its developers, whose names
|
||||
' are too numerous to list here. Please refer to the COPYRIGHT
|
||||
' file distributed with this source distribution.
|
||||
'
|
||||
' This program is free software; you can redistribute it and/or
|
||||
' modify it under the terms of the GNU General Public License
|
||||
' as published by the Free Software Foundation, version 2
|
||||
' of the License.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
' GNU General Public License for more details.
|
||||
'
|
||||
' You should have received a copy of the GNU General Public License
|
||||
' along with this program; if not, write to the Free Software
|
||||
' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
'
|
||||
'/
|
||||
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
' This script calls the iscc tool to generate a Inno Setup Windows installer for ScummVM
|
||||
'
|
||||
' It tries to read the Inno Setup installation folder from the registry and then calls the
|
||||
' command line script compiler to create the installer.
|
||||
'
|
||||
' This is called from the postbuild.cmd batch file
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
'================================================================
|
||||
' TODO: Reduce duplication with revision.vbs script
|
||||
' (ReadRegistryKey and ParseCommandLine are identical)
|
||||
'================================================================
|
||||
|
||||
Option Explicit
|
||||
|
||||
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
|
||||
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
|
||||
|
||||
' Folders
|
||||
Dim rootFolder : rootFolder = ""
|
||||
Dim targetFolder : targetFolder = ""
|
||||
|
||||
' Parse our command line arguments
|
||||
If ParseCommandLine() Then
|
||||
CreateInstaller()
|
||||
End If
|
||||
|
||||
'////////////////////////////////////////////////////////////////
|
||||
'// Installer creation
|
||||
'////////////////////////////////////////////////////////////////
|
||||
Sub CreateInstaller()
|
||||
' Get inno installation folder
|
||||
Dim innoPath : innoPath = GetInnoPath()
|
||||
If (innoPath = "") Then
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
' Build command line
|
||||
Dim commandLine : commandLine = """" & innoPath & "\iscc.exe"" /Qp" & _
|
||||
" /O""" & targetFolder & """" & _
|
||||
" """ & rootFolder & "\dists\win32\scummvm.iss"""
|
||||
|
||||
Dim oExec: Set oExec = WshShell.Exec(commandline)
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error running iscc.exe!"
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
' Wait till the application is finished ...
|
||||
Dim ostdOut : Set oStdOut = oExec.StdOut
|
||||
Do While oExec.Status = 0
|
||||
If Not ostdOut.AtEndOfStream Then
|
||||
Wscript.StdErr.WriteLine ostdOut.ReadAll
|
||||
End If
|
||||
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
|
||||
If oExec.ExitCode <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error while creating installer!"
|
||||
Exit Sub
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Function GetInnoPath()
|
||||
' Get the directory where Inno Setup (should) reside(s)
|
||||
Dim sInno
|
||||
|
||||
' First, try with 32-bit architecture
|
||||
sInno = ReadRegistryKey("HKLM", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 5_is1", "InstallLocation", 32)
|
||||
|
||||
If sInno = "" Or IsNull(sInno) Then
|
||||
' No 32-bit version of Inno Setup installed, try 64-bit version (doesn't hurt on 32-bit machines, it returns nothing or is ignored)
|
||||
sInno = ReadRegistryKey("HKLM", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 5_is1", "InstallLocation", 64)
|
||||
End If
|
||||
|
||||
' Check if Inno Setup is present
|
||||
If sInno = "" Then
|
||||
Wscript.StdErr.WriteLine "Inno Setup not installed!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
GetInnoPath = sInno
|
||||
End Function
|
||||
|
||||
'////////////////////////////////////////////////////////////////
|
||||
'// Utilities
|
||||
'////////////////////////////////////////////////////////////////
|
||||
Function ParseCommandLine()
|
||||
ParseCommandLine = True
|
||||
|
||||
If Wscript.Arguments.Count <> 2 Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid number of arguments (was: " & Wscript.Arguments.Count & ", expected: 2)"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Get our arguments
|
||||
rootFolder = Wscript.Arguments.Item(0)
|
||||
targetFolder = Wscript.Arguments.Item(1)
|
||||
|
||||
' Check that the folders are valid
|
||||
If Not FSO.FolderExists(rootFolder) Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid root folder (" & rootFolder & ")"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If Not FSO.FolderExists(targetFolder) Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid target folder (" & targetFolder & ")"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Set absolute paths
|
||||
rootFolder = FSO.GetAbsolutePathName(rootFolder)
|
||||
targetFolder = FSO.GetAbsolutePathName(targetFolder)
|
||||
End Function
|
||||
|
||||
Function ReadRegistryKey(shive, subkey, valuename, architecture)
|
||||
Dim hiveKey, objCtx, objLocator, objServices, objReg, Inparams, Outparams
|
||||
|
||||
' First, get the Registry Provider for the requested architecture
|
||||
Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
|
||||
objCtx.Add "__ProviderArchitecture", architecture ' Must be 64 of 32
|
||||
Set objLocator = CreateObject("Wbemscripting.SWbemLocator")
|
||||
Set objServices = objLocator.ConnectServer("","root\default","","",,,,objCtx)
|
||||
Set objReg = objServices.Get("StdRegProv")
|
||||
|
||||
' Check the hive and give it the right value
|
||||
Select Case shive
|
||||
Case "HKCR", "HKEY_CLASSES_ROOT"
|
||||
hiveKey = &h80000000
|
||||
Case "HKCU", "HKEY_CURRENT_USER"
|
||||
hiveKey = &H80000001
|
||||
Case "HKLM", "HKEY_LOCAL_MACHINE"
|
||||
hiveKey = &h80000002
|
||||
Case "HKU", "HKEY_USERS"
|
||||
hiveKey = &h80000003
|
||||
Case "HKCC", "HKEY_CURRENT_CONFIG"
|
||||
hiveKey = &h80000005
|
||||
Case "HKDD", "HKEY_DYN_DATA" ' Only valid for Windows 95/98
|
||||
hiveKey = &h80000006
|
||||
Case Else
|
||||
MsgBox "Hive not valid (ReadRegistryKey)"
|
||||
End Select
|
||||
|
||||
Set Inparams = objReg.Methods_("GetStringValue").Inparameters
|
||||
Inparams.Hdefkey = hiveKey
|
||||
Inparams.Ssubkeyname = subkey
|
||||
Inparams.Svaluename = valuename
|
||||
Set Outparams = objReg.ExecMethod_("GetStringValue", Inparams,,objCtx)
|
||||
|
||||
ReadRegistryKey = Outparams.SValue
|
||||
End Function
|
||||
65
devtools/create_project/scripts/postbuild.cmd
Normal file
65
devtools/create_project/scripts/postbuild.cmd
Normal file
@@ -0,0 +1,65 @@
|
||||
@echo off
|
||||
|
||||
REM ---------------------------------------------------------------
|
||||
REM -- Post-Build Script
|
||||
REM ---------------------------------------------------------------
|
||||
REM
|
||||
REM Copy engine data and required dlls to the
|
||||
REM output folder and optionally create an installer
|
||||
REM
|
||||
REM Expected parameters
|
||||
REM Root folder
|
||||
REM Output folder
|
||||
REM SDL version
|
||||
REM Libs folder
|
||||
REM Installer ("1" to build, "0" to skip)
|
||||
|
||||
if "%~1"=="" goto error_root
|
||||
if "%~2"=="" goto error_output
|
||||
if "%~3"=="" goto error_sdl
|
||||
if "%~4"=="" goto error_libs
|
||||
if "%~5"=="" goto error_installer
|
||||
|
||||
echo Copying data files
|
||||
echo.
|
||||
|
||||
xcopy /F /Y "%~4/%~3.dll" "%~2" 1>NUL 2>&1
|
||||
xcopy /F /Y "%~4/WinSparkle.dll" "%~2" 1>NUL 2>&1
|
||||
xcopy /F /Y "%~1/backends/vkeybd/packs/vkeybd_default.zip" "%~2" 1>NUL 2>&1
|
||||
xcopy /F /Y "%~1/backends/vkeybd/packs/vkeybd_small.zip" "%~2" 1>NUL 2>&1
|
||||
|
||||
|
||||
if "%~5"=="0" goto done
|
||||
|
||||
echo Running installer script
|
||||
echo.
|
||||
@call cscript "%~1/devtools/create_project/scripts/installer.vbs" "%~1" "%~2" 1>NUL
|
||||
if not %errorlevel% == 0 goto error_script
|
||||
goto done
|
||||
|
||||
:error_root
|
||||
echo Invalid root folder (%~1)!
|
||||
goto done
|
||||
|
||||
:error_output
|
||||
echo Invalid output folder (%~2)!
|
||||
goto done
|
||||
|
||||
:error_sdl
|
||||
echo Invalid SDL parameter (was: %~3, allowed: SDL, SDL2)!
|
||||
goto done
|
||||
|
||||
:error_libs
|
||||
echo Invalid libs folder (%~4)!
|
||||
goto done
|
||||
|
||||
:error_installer
|
||||
echo Invalid installer parameter. Should be "0" or "1" (was %~5)!
|
||||
goto done
|
||||
|
||||
:error_script:
|
||||
echo An error occurred while running the installer script!
|
||||
goto done
|
||||
|
||||
:done
|
||||
exit /B0
|
||||
33
devtools/create_project/scripts/prebuild.cmd
Normal file
33
devtools/create_project/scripts/prebuild.cmd
Normal file
@@ -0,0 +1,33 @@
|
||||
@echo off
|
||||
|
||||
REM ---------------------------------------------------------------
|
||||
REM -- Pre-Build Script
|
||||
REM ---------------------------------------------------------------
|
||||
REM
|
||||
REM Generate file with revision number
|
||||
REM
|
||||
REM Expected parameters
|
||||
REM Root folder (the source root folder)
|
||||
REM Target folder (the build output folder, will be used to copy internal_revision.h)
|
||||
|
||||
if "%~1"=="" goto error_root
|
||||
if "%~2"=="" goto error_target
|
||||
|
||||
REM Run the revision script
|
||||
@call cscript "%~1/devtools/create_project/scripts/revision.vbs" "%~1" "%~2" 1>NUL
|
||||
if not %errorlevel% == 0 goto error_script
|
||||
goto done
|
||||
|
||||
:error_root
|
||||
echo Invalid root folder (%~1)!
|
||||
goto done
|
||||
|
||||
:error_target
|
||||
echo Invalid target folder (%~2)!
|
||||
goto done
|
||||
|
||||
:error_script:
|
||||
echo An error occurred while running the revision script!
|
||||
|
||||
:done
|
||||
exit /B0
|
||||
505
devtools/create_project/scripts/revision.vbs
Normal file
505
devtools/create_project/scripts/revision.vbs
Normal file
@@ -0,0 +1,505 @@
|
||||
'
|
||||
' ScummVM - Graphic Adventure Engine
|
||||
'
|
||||
' ScummVM is the legal property of its developers, whose names
|
||||
' are too numerous to list here. Please refer to the COPYRIGHT
|
||||
' file distributed with this source distribution.
|
||||
'
|
||||
' This program is free software; you can redistribute it and/or
|
||||
' modify it under the terms of the GNU General Public License
|
||||
' as published by the Free Software Foundation, version 2
|
||||
' of the License.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
' GNU General Public License for more details.
|
||||
'
|
||||
' You should have received a copy of the GNU General Public License
|
||||
' along with this program; if not, write to the Free Software
|
||||
' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
'
|
||||
' Based off OpenTTD determineversion.vbs (released under GPL version 2)
|
||||
'
|
||||
'/
|
||||
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
' This script tries to determine a revision number based on the current working tree
|
||||
' by trying revision control tools in the following order:
|
||||
' - git (with hg-git detection)
|
||||
' - mercurial
|
||||
' - TortoiseSVN
|
||||
' - SVN
|
||||
'
|
||||
' It then writes a new header file to be included during build, with the revision
|
||||
' information, the current branch, the revision control system (when not git) and
|
||||
' a flag when the tree is dirty.
|
||||
'
|
||||
' This is called from the prebuild.cmd batch file
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Option Explicit
|
||||
|
||||
' Working copy check priority:
|
||||
' True: TortoiseSVN -> SVN -> Git -> Hg
|
||||
' False: Git -> Hg -> TortoiseSVN -> SVN
|
||||
Dim prioritySVN: prioritySVN = False
|
||||
|
||||
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
|
||||
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
|
||||
|
||||
' Folders
|
||||
Dim rootFolder : rootFolder = ""
|
||||
Dim targetFolder : targetFolder = ""
|
||||
|
||||
' Info variables
|
||||
Dim tool : tool = ""
|
||||
Dim branch : branch = "trunk"
|
||||
Dim revision : revision = ""
|
||||
Dim modified : modified = False
|
||||
|
||||
' Parse our command line arguments
|
||||
If ParseCommandLine() Then
|
||||
' Determine the revision and update the props file with the revision numbers
|
||||
DetermineRevision()
|
||||
End If
|
||||
|
||||
'////////////////////////////////////////////////////////////////
|
||||
'// Revision checking
|
||||
'////////////////////////////////////////////////////////////////
|
||||
Sub DetermineRevision()
|
||||
Wscript.StdErr.WriteLine "Determining current revision:"
|
||||
|
||||
' Set the current directory to the root folder
|
||||
WshShell.CurrentDirectory = rootFolder
|
||||
|
||||
' Try until we find a proper working copy
|
||||
If (prioritySVN) Then
|
||||
If Not DetermineTortoiseSVNVersion() Then
|
||||
If Not DetermineSVNVersion() Then
|
||||
If Not DetermineGitVersion() Then
|
||||
If Not DetermineHgVersion() Then
|
||||
Wscript.StdErr.WriteLine "Could not determine the current revision, skipping..."
|
||||
OutputRevisionHeader ""
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Else
|
||||
If Not DetermineGitVersion() Then
|
||||
If Not DetermineHgVersion() Then
|
||||
If Not DetermineTortoiseSVNVersion() Then
|
||||
If Not DetermineSVNVersion() Then
|
||||
Wscript.StdErr.WriteLine "Could not determine the current revision, skipping..."
|
||||
OutputRevisionHeader ""
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
Dim outputInfo : outputInfo = "Found revision " & revision & " on branch " & branch
|
||||
|
||||
' Setup our revision string
|
||||
Dim revisionString : revisionString = revision
|
||||
|
||||
If (modified) Then
|
||||
revisionString = revisionString & "-dirty"
|
||||
outputInfo = outputInfo & " (dirty)"
|
||||
End If
|
||||
|
||||
' If we are not on trunk, add the branch name to the revision string
|
||||
If (branch <> "trunk" And branch <> "master" And branch <> "") Then
|
||||
revisionString = revisionString & "(" & branch & ")"
|
||||
End If
|
||||
|
||||
' Add the DVCS name at the end (when not git)
|
||||
If (tool <> "git") Then
|
||||
revisionString = revisionString & "-" & tool
|
||||
outputInfo = outputInfo & " using " & tool
|
||||
End If
|
||||
|
||||
Wscript.StdErr.WriteLine outputInfo & vbCrLf
|
||||
|
||||
OutputRevisionHeader revisionString
|
||||
End Sub
|
||||
|
||||
' Output revision header file
|
||||
Sub OutputRevisionHeader(str)
|
||||
FSO.CopyFile rootFolder & "\\base\\internal_revision.h.in", targetFolder & "\\internal_revision.h.tmp"
|
||||
FindReplaceInFile targetFolder & "\\internal_revision.h.tmp", "@REVISION@", str
|
||||
CompareFileAndReplace targetFolder & "\\internal_revision.h.tmp", targetFolder & "\\internal_revision.h"
|
||||
End Sub
|
||||
|
||||
Function DetermineTortoiseSVNVersion()
|
||||
Err.Clear
|
||||
On Error Resume Next
|
||||
DetermineTortoiseSVNVersion = False
|
||||
Wscript.StdErr.Write " TortoiseSVN... "
|
||||
tool = "svn"
|
||||
|
||||
' Get the directory where TortoiseSVN (should) reside(s)
|
||||
Dim sTortoise
|
||||
|
||||
' First, try with 32-bit architecture
|
||||
sTortoise = ReadRegistryKey("HKLM", "SOFTWARE\TortoiseSVN", "Directory", 32)
|
||||
|
||||
If sTortoise = "" Or IsNull(sTortoise) Then
|
||||
' No 32-bit version of TortoiseSVN installed, try 64-bit version (doesn't hurt on 32-bit machines, it returns nothing or is ignored)
|
||||
sTortoise = ReadRegistryKey("HKLM", "SOFTWARE\TortoiseSVN", "Directory", 64)
|
||||
End If
|
||||
|
||||
' Check if Tortoise is present
|
||||
If sTortoise = "" Then
|
||||
Wscript.StdErr.WriteLine "TortoiseSVN not installed!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' If TortoiseSVN is installed, try to get the revision number
|
||||
Dim SubWCRev : Set SubWCRev = WScript.CreateObject("SubWCRev.object")
|
||||
SubWCRev.GetWCInfo rootFolder, 0, 0
|
||||
|
||||
' Check if this is a working copy
|
||||
If Not SubWCRev.IsSvnItem Then
|
||||
Wscript.StdErr.WriteLine "Not a working copy!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
revision = SubWCRev.Revision
|
||||
|
||||
' Check for modifications
|
||||
If SubWCRev.HasModifications Then modified = True
|
||||
|
||||
If revision = "" Then
|
||||
Wscript.StdErr.WriteLine "No revision found!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
DetermineTortoiseSVNVersion = True
|
||||
End Function
|
||||
|
||||
Function DetermineSVNVersion()
|
||||
Err.Clear
|
||||
On Error Resume Next
|
||||
DetermineSVNVersion = False
|
||||
Wscript.StdErr.Write " SVN... "
|
||||
tool = "svn"
|
||||
|
||||
' Set the environment to English
|
||||
WshShell.Environment("PROCESS")("LANG") = "en"
|
||||
|
||||
' Do we have subversion installed? Check immediately whether we've got a modified WC.
|
||||
Dim oExec: Set oExec = WshShell.Exec("svnversion " & rootFolder)
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "SVN not installed!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
|
||||
Dim line: line = OExec.StdOut.ReadLine()
|
||||
If line = "exported" Then
|
||||
Wscript.StdErr.WriteLine "Not a working copy!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If InStr(line, "M") Then
|
||||
modified = True
|
||||
End If
|
||||
|
||||
' And use svn info to get the correct revision and branch information.
|
||||
Set oExec = WshShell.Exec("svn info " & rootFolder)
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "No revision found!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
Do
|
||||
line = OExec.StdOut.ReadLine()
|
||||
If InStr(line, "Last Changed Rev") Then
|
||||
revision = Mid(line, 19)
|
||||
End If
|
||||
Loop While Not OExec.StdOut.atEndOfStream
|
||||
|
||||
If revision = 0 Then
|
||||
Wscript.StdErr.WriteLine "No revision found!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
DetermineSVNVersion = True
|
||||
End Function
|
||||
|
||||
Function DetermineGitVersion()
|
||||
Err.Clear
|
||||
On Error Resume Next
|
||||
DetermineGitVersion = False
|
||||
Dim line
|
||||
Wscript.StdErr.Write " Git... "
|
||||
tool = "git"
|
||||
|
||||
' First check if we have both a .git & .hg folders (in case hg-git has been set up to have the git folder at the working copy level)
|
||||
If FSO.FolderExists(rootFolder & "/.git") And FSO.FolderExists(rootFolder & "/.hg") Then
|
||||
Wscript.StdErr.WriteLine "Mercurial clone with git repository in tree!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Set the environment to English
|
||||
WshShell.Environment("PROCESS")("LANG") = "en"
|
||||
|
||||
' Detect if we are using msysgit that has a cmd script in the path instead of an exe...
|
||||
Dim gitPath : gitPath = "git "
|
||||
Dim oExec : Set oExec = WshShell.Exec("git")
|
||||
If Err.Number <> 0 Then
|
||||
gitPath = "git.cmd "
|
||||
End If
|
||||
|
||||
Err.Clear
|
||||
Set oExec = WshShell.Exec(gitPath & "rev-parse --verify HEAD")
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Git not installed!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
|
||||
If oExec.ExitCode <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error parsing git revision!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Get the version hash
|
||||
Dim hash : hash = oExec.StdOut.ReadLine()
|
||||
|
||||
' Make sure index is in sync with disk
|
||||
Set oExec = WshShell.Exec(gitPath & "update-index --refresh --unmerged")
|
||||
If Err.Number = 0 Then
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
End If
|
||||
|
||||
Set oExec = WshShell.Exec(gitPath & "diff-index --quiet HEAD " & rootFolder)
|
||||
If oExec.ExitCode <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error parsing git revision!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
|
||||
If oExec.ExitCode = 1 Then
|
||||
modified = True
|
||||
End If
|
||||
|
||||
' Get branch name
|
||||
Set oExec = WshShell.Exec(gitPath & "symbolic-ref HEAD")
|
||||
If Err.Number = 0 Then
|
||||
line = oExec.StdOut.ReadLine()
|
||||
line = Mid(line, InStrRev(line, "/") + 1)
|
||||
If line <> "master" Then
|
||||
branch = line
|
||||
End If
|
||||
End If
|
||||
|
||||
' Get revision description
|
||||
Set oExec = WshShell.Exec(gitPath & "describe --match desc/*")
|
||||
If Err.Number = 0 Then
|
||||
line = oExec.StdOut.ReadLine()
|
||||
line = Mid(line, InStr(line, "-") + 1)
|
||||
If line <> "" Then
|
||||
revision = line
|
||||
End If
|
||||
End If
|
||||
|
||||
' Fallback to abbreviated revision number if needed
|
||||
If revision = "" Then
|
||||
revision = Mid(hash, 1, 7)
|
||||
End If
|
||||
|
||||
DetermineGitVersion = True
|
||||
End Function
|
||||
|
||||
Function DetermineHgVersion()
|
||||
Err.Clear
|
||||
On Error Resume Next
|
||||
DetermineHgVersion = False
|
||||
Wscript.StdErr.Write " Mercurial... "
|
||||
tool = "hg"
|
||||
|
||||
Err.Clear
|
||||
Dim oExec: Set oExec = WshShell.Exec("hg parents --template ""{rev}:{node|short}""")
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Mercurial not installed!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
WScript.Sleep 100
|
||||
Loop
|
||||
|
||||
If oExec.ExitCode <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error parsing mercurial revision!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
Dim info : info = Split(OExec.StdOut.ReadLine(), ":")
|
||||
Dim version : version = info(0)
|
||||
Dim hash : hash = info(1)
|
||||
|
||||
Set oExec = WshShell.Exec("hg status " & rootFolder)
|
||||
If Err.Number <> 0 Then
|
||||
Wscript.StdErr.WriteLine "Error parsing mercurial revision!"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Check for modifications
|
||||
Do
|
||||
line = OExec.StdOut.ReadLine()
|
||||
If Len(line) > 0 And Mid(line, 1, 1) <> "?" Then
|
||||
modified = True
|
||||
Exit Do
|
||||
End If
|
||||
Loop While Not OExec.StdOut.atEndOfStream
|
||||
|
||||
' Check for branch
|
||||
Set oExec = WshShell.Exec("hg branch")
|
||||
If Err.Number = 0 Then
|
||||
line = OExec.StdOut.ReadLine()
|
||||
If line <> "default" Then
|
||||
branch = line
|
||||
End If
|
||||
End If
|
||||
|
||||
' Check for SVN clone
|
||||
Set oExec = WshShell.Exec("hg log -f -l 1 --template ""{svnrev}\n"" --cwd " & rootFolder)
|
||||
If Err.Number = 0 Then
|
||||
revision = Mid(OExec.StdOut.ReadLine(), 7)
|
||||
revision = Mid(revision, 1, InStr(revision, ")") - 1)
|
||||
tool = "svn-hg"
|
||||
End If
|
||||
|
||||
' Fallback to abbreviated revision number
|
||||
If revision = "" Then
|
||||
revision = version & "(" & hash & ")"
|
||||
End If
|
||||
|
||||
DetermineHgVersion = True
|
||||
End Function
|
||||
|
||||
'////////////////////////////////////////////////////////////////
|
||||
'// Utilities
|
||||
'////////////////////////////////////////////////////////////////
|
||||
Function ParseCommandLine()
|
||||
ParseCommandLine = True
|
||||
|
||||
If Wscript.Arguments.Count <> 2 Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid number of arguments (was: " & Wscript.Arguments.Count & ", expected: 2)"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Get our arguments
|
||||
rootFolder = Wscript.Arguments.Item(0)
|
||||
targetFolder = Wscript.Arguments.Item(1)
|
||||
|
||||
' Check that the folders are valid
|
||||
If Not FSO.FolderExists(rootFolder) Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid root folder (" & rootFolder & ")"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If Not FSO.FolderExists(targetFolder) Then
|
||||
Wscript.StdErr.WriteLine "[Error] Invalid target folder (" & targetFolder & ")"
|
||||
|
||||
ParseCommandLine = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' Set absolute paths
|
||||
rootFolder = FSO.GetAbsolutePathName(rootFolder)
|
||||
targetFolder = FSO.GetAbsolutePathName(targetFolder)
|
||||
End Function
|
||||
|
||||
Function ReadRegistryKey(shive, subkey, valuename, architecture)
|
||||
Dim hiveKey, objCtx, objLocator, objServices, objReg, Inparams, Outparams
|
||||
|
||||
' First, get the Registry Provider for the requested architecture
|
||||
Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
|
||||
objCtx.Add "__ProviderArchitecture", architecture ' Must be 64 of 32
|
||||
Set objLocator = CreateObject("Wbemscripting.SWbemLocator")
|
||||
Set objServices = objLocator.ConnectServer("","root\default","","",,,,objCtx)
|
||||
Set objReg = objServices.Get("StdRegProv")
|
||||
|
||||
' Check the hive and give it the right value
|
||||
Select Case shive
|
||||
Case "HKCR", "HKEY_CLASSES_ROOT"
|
||||
hiveKey = &h80000000
|
||||
Case "HKCU", "HKEY_CURRENT_USER"
|
||||
hiveKey = &H80000001
|
||||
Case "HKLM", "HKEY_LOCAL_MACHINE"
|
||||
hiveKey = &h80000002
|
||||
Case "HKU", "HKEY_USERS"
|
||||
hiveKey = &h80000003
|
||||
Case "HKCC", "HKEY_CURRENT_CONFIG"
|
||||
hiveKey = &h80000005
|
||||
Case "HKDD", "HKEY_DYN_DATA" ' Only valid for Windows 95/98
|
||||
hiveKey = &h80000006
|
||||
Case Else
|
||||
MsgBox "Hive not valid (ReadRegistryKey)"
|
||||
End Select
|
||||
|
||||
Set Inparams = objReg.Methods_("GetStringValue").Inparameters
|
||||
Inparams.Hdefkey = hiveKey
|
||||
Inparams.Ssubkeyname = subkey
|
||||
Inparams.Svaluename = valuename
|
||||
Set Outparams = objReg.ExecMethod_("GetStringValue", Inparams,,objCtx)
|
||||
|
||||
ReadRegistryKey = Outparams.SValue
|
||||
End Function
|
||||
|
||||
Sub FindReplaceInFile(filename, to_find, replacement)
|
||||
Dim file, data
|
||||
Set file = FSO.OpenTextFile(filename, 1, 0, 0)
|
||||
data = file.ReadAll
|
||||
file.Close
|
||||
data = Replace(data, to_find, replacement)
|
||||
Set file = FSO.CreateTextFile(filename, -1, 0)
|
||||
file.Write data
|
||||
file.Close
|
||||
End Sub
|
||||
|
||||
Sub CompareFileAndReplace(src_filename, dst_filename)
|
||||
Dim file, src_data, dst_data
|
||||
Set file = FSO.OpenTextFile(src_filename, 1, 0, 0)
|
||||
src_data = file.ReadAll
|
||||
file.Close
|
||||
If Not FSO.FileExists(dst_filename) Then
|
||||
FSO.CopyFile src_filename, dst_filename, True
|
||||
Else
|
||||
Set file = FSO.OpenTextFile(dst_filename, 1, 0, 0)
|
||||
dst_data = file.ReadAll
|
||||
file.Close
|
||||
If StrComp(src_data, dst_data, vbBinaryCompare) <> 0 Then
|
||||
' Files are different, overwrite the destination
|
||||
FSO.CopyFile src_filename, dst_filename, True
|
||||
End If
|
||||
End If
|
||||
' Remove temporary source
|
||||
FSO.DeleteFile src_filename
|
||||
End Sub
|
||||
150
devtools/create_project/scripts/scummvm.natvis
Normal file
150
devtools/create_project/scripts/scummvm.natvis
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Debug visualizers for a few common ScummVM types for Visual Studio 2012 and up.
|
||||
|
||||
To use, copy this file into Documents\Visual Studio 20xx\Visualizers.
|
||||
-->
|
||||
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<UIVisualizer ServiceId="{A452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" MenuName="Add to Image Watch"/>
|
||||
|
||||
<Type Name="Graphics::Surface">
|
||||
<UIVisualizer ServiceId="{A452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" />
|
||||
</Type>
|
||||
|
||||
<Type Name="Graphics::Surface">
|
||||
<Expand>
|
||||
<Synthetic Name="[type]">
|
||||
<DisplayString>UINT8</DisplayString>
|
||||
</Synthetic>
|
||||
<Item Name="[channels]" Condition="format.bytesPerPixel==1">1</Item>
|
||||
<Item Name="[channels]" Condition="format.bytesPerPixel==2">2</Item>
|
||||
<Synthetic Name="[channels]" Condition="format.bytesPerPixel==3">
|
||||
<DisplayString>RGB</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[channels]" Condition="format.bytesPerPixel==4">
|
||||
<DisplayString>RGBA</DisplayString>
|
||||
</Synthetic>
|
||||
<Item Name="[width]">w</Item>
|
||||
<Item Name="[height]">h</Item>
|
||||
<Item Name="[stride]">pitch</Item>
|
||||
<Item Name="[data]">pixels</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::Array<*>">
|
||||
<DisplayString>{{ size={_size} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<Item Name="[capacity]">_capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>_size</Size>
|
||||
<ValuePointer>_storage</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::HashMap<*,*,*,*>">
|
||||
<DisplayString>{{ size={_size} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<Item Name="[capacity]">_mask + 1</Item>
|
||||
<Item Name="[deleted]">_deleted</Item>
|
||||
<CustomListItems MaxItemsPerView="5000" ExcludeView="Test">
|
||||
<Variable Name="ctr" InitialValue="0" />
|
||||
<Size>_size</Size>
|
||||
<Loop>
|
||||
<Break Condition="ctr > _mask" />
|
||||
<Item Condition="_storage[ctr] > 1" Name="[{_storage[ctr]->_key}]">*_storage[ctr],view(MapHelper)</Item>
|
||||
<Exec>ctr++</Exec>
|
||||
</Loop>
|
||||
</CustomListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::HashMap<*,*,*,*>::Node" IncludeView="MapHelper">
|
||||
<DisplayString>{_value}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::HashMap<*,*,*,*>::IteratorImpl<*>">
|
||||
<DisplayString>{_hashmap->_storage[_idx],na}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[ptr]">_hashmap->_storage[_idx]</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::List<*>">
|
||||
<DisplayString Condition="&_anchor == _anchor._next">{{ empty }}</DisplayString>
|
||||
<DisplayString Condition="&_anchor != _anchor._next">{{ non-empty }}</DisplayString>
|
||||
<Expand>
|
||||
<CustomListItems Condition="&_anchor != _anchor._next">
|
||||
<Variable Name="head" InitialValue="&_anchor"/>
|
||||
<Variable Name="iter" InitialValue="_anchor._next"/>
|
||||
<Loop>
|
||||
<Break Condition="iter == head"/>
|
||||
<Item>((Common::ListInternal::Node<$T1>*)iter)->_data</Item>
|
||||
<Exec>iter = iter->_next</Exec>
|
||||
</Loop>
|
||||
</CustomListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::ListInternal::Node<*>">
|
||||
<DisplayString>{_data}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::ListInternal::Iterator<*>">
|
||||
<AlternativeType Name="Common::ListInternal::ConstIterator<*>" />
|
||||
<DisplayString>{((Common::ListInternal::Node<$T1>*)_node)->_data}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[ptr]">((Common::ListInternal::Node<$T1>*)_node)->_data</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::String">
|
||||
<DisplayString>{_str,na}</DisplayString>
|
||||
<StringView>_str,na</StringView>
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<Item Condition="_str != _storage" Name="[capacity]">_extern._capacity</Item>
|
||||
<Item Condition="_str != _storage && _extern._refCount != 0" Name="[refCount]">*_extern._refCount</Item>
|
||||
<ArrayItems>
|
||||
<Size>_size</Size>
|
||||
<ValuePointer>_str</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::U32String">
|
||||
<DisplayString>{_str,s32}</DisplayString>
|
||||
<StringView>_str,s32</StringView>
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<Item Condition="_str != _storage" Name="[capacity]">_extern._capacity</Item>
|
||||
<Item Condition="_str != _storage && _extern._refCount != 0" Name="[refCount]">*_extern._refCount</Item>
|
||||
<ArrayItems>
|
||||
<Size>_size</Size>
|
||||
<ValuePointer>_str</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::WeakPtr<*>">
|
||||
<DisplayString Condition="_pointer == 0">nullptr</DisplayString>
|
||||
<DisplayString Condition="_pointer != 0">{*_pointer}</DisplayString>
|
||||
<Expand>
|
||||
<Item Condition="_pointer != 0" Name="[ptr]">_pointer</Item>
|
||||
<Item Condition="_tracker != 0" Name="[refCount]">_tracker->_strongRefCount</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Common::SharedPtr<*>">
|
||||
<DisplayString Condition="_pointer == 0">nullptr</DisplayString>
|
||||
<DisplayString Condition="_pointer != 0">{*_pointer}</DisplayString>
|
||||
<Expand>
|
||||
<Item Condition="_pointer != 0" Name="[ptr]">_pointer</Item>
|
||||
<Item Condition="_tracker != 0" Name="[refCount]">_tracker->_strongRefCount</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
||||
1831
devtools/create_project/xcode.cpp
Normal file
1831
devtools/create_project/xcode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
356
devtools/create_project/xcode.h
Normal file
356
devtools/create_project/xcode.h
Normal file
@@ -0,0 +1,356 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_XCODE_H
|
||||
#define TOOLS_CREATE_PROJECT_XCODE_H
|
||||
|
||||
#include "create_project.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
class XcodeProvider final : public ProjectProvider {
|
||||
public:
|
||||
XcodeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, StringList &global_errors);
|
||||
|
||||
protected:
|
||||
|
||||
void createWorkspace(const BuildSetup &setup) final;
|
||||
|
||||
void createOtherBuildFiles(const BuildSetup &setup) final;
|
||||
|
||||
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final;
|
||||
|
||||
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
|
||||
const std::string &objPrefix, const std::string &filePrefix,
|
||||
const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
|
||||
|
||||
private:
|
||||
enum {
|
||||
kSettingsAsList = 0x01,
|
||||
kSettingsSingleItem = 0x02,
|
||||
kSettingsNoQuote = 0x04,
|
||||
kSettingsQuoteVariable = 0x08,
|
||||
kSettingsNoValue = 0x10
|
||||
};
|
||||
|
||||
// File properties
|
||||
struct FileProperty {
|
||||
std::string _fileEncoding;
|
||||
std::string _lastKnownFileType;
|
||||
std::string _fileName;
|
||||
std::string _filePath;
|
||||
std::string _sourceTree;
|
||||
|
||||
FileProperty(const std::string &fileType = "", const std::string &name = "", const std::string &path = "", const std::string &source = "")
|
||||
: _fileEncoding(""), _lastKnownFileType(fileType), _fileName(name), _filePath(path), _sourceTree(source) {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// XCObject and children
|
||||
typedef std::vector<std::string> ValueList;
|
||||
|
||||
struct Entry {
|
||||
std::string _value;
|
||||
std::string _comment;
|
||||
|
||||
Entry(std::string val, std::string cmt) : _value(val), _comment(cmt) {}
|
||||
};
|
||||
|
||||
typedef std::vector<Entry> EntryList;
|
||||
|
||||
struct Setting {
|
||||
EntryList _entries;
|
||||
int _flags;
|
||||
int _indent;
|
||||
int _order;
|
||||
|
||||
Setting(std::string value = "", std::string comment = "", int flgs = 0, int idt = 0, int ord = -1) : _flags(flgs), _indent(idt), _order(ord) {
|
||||
_entries.push_back(Entry(value, comment));
|
||||
}
|
||||
|
||||
Setting(ValueList values, int flgs = 0, int idt = 0, int ord = -1) : _flags(flgs), _indent(idt), _order(ord) {
|
||||
for (unsigned int i = 0; i < values.size(); i++)
|
||||
_entries.push_back(Entry(values[i], ""));
|
||||
}
|
||||
|
||||
Setting(EntryList ents, int flgs = 0, int idt = 0, int ord = -1) : _entries(ents), _flags(flgs), _indent(idt), _order(ord) {}
|
||||
|
||||
void addEntry(std::string value, std::string comment = "") {
|
||||
_entries.push_back(Entry(value, comment));
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Setting> SettingList;
|
||||
typedef std::pair<std::string, Setting> SettingPair;
|
||||
typedef std::vector<SettingPair> OrderedSettingList;
|
||||
|
||||
static bool OrderSortPredicate(const SettingPair &s1, const SettingPair &s2) {
|
||||
return s1.second._order < s2.second._order;
|
||||
}
|
||||
|
||||
struct Property {
|
||||
public:
|
||||
SettingList _settings;
|
||||
int _flags;
|
||||
bool _hasOrder;
|
||||
|
||||
Property() : _flags(0), _hasOrder(false) {}
|
||||
|
||||
// Constructs a simple Property
|
||||
Property(std::string name, std::string value = "", std::string comment = "", int flgs = 0, int indent = 0, bool order = false) : _flags(flgs), _hasOrder(order) {
|
||||
_settings[name] = Setting(value, comment, _flags, indent);
|
||||
}
|
||||
|
||||
Property(std::string name, ValueList values, int flgs = 0, int indent = 0, bool order = false) : _flags(flgs), _hasOrder(order) {
|
||||
_settings[name] = Setting(values, _flags, indent);
|
||||
}
|
||||
|
||||
OrderedSettingList getOrderedSettingList() {
|
||||
OrderedSettingList list;
|
||||
|
||||
// Prepare vector to sort
|
||||
for (SettingList::const_iterator setting = _settings.begin(); setting != _settings.end(); ++setting)
|
||||
list.push_back(SettingPair(setting->first, setting->second));
|
||||
|
||||
// Sort vector using setting order
|
||||
if (_hasOrder)
|
||||
std::sort(list.begin(), list.end(), OrderSortPredicate);
|
||||
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Property> PropertyList;
|
||||
|
||||
// Main object struct
|
||||
// This is all a big hack unfortunately, but making everything all properly abstracted would
|
||||
// be overkill since we only have to generate a single project
|
||||
struct Object {
|
||||
public:
|
||||
std::string _id; // Unique identifier for this object
|
||||
std::string _name; // Name (may not be unique - for ex. configuration entries)
|
||||
std::string _refType; // Type of object this references (if any)
|
||||
std::string _comment; // Main comment (empty for no comment)
|
||||
|
||||
PropertyList _properties; // List of object properties, including output configuration
|
||||
|
||||
// Constructs an object and add a default type property
|
||||
Object(XcodeProvider *objectParent, std::string objectId, std::string objectName, std::string objectType, std::string objectRefType = "", std::string objectComment = "")
|
||||
: _id(objectId), _name(objectName), _refType(objectRefType), _comment(objectComment), _parent(objectParent) {
|
||||
assert(objectParent);
|
||||
assert(!objectId.empty());
|
||||
assert(!objectName.empty());
|
||||
assert(!objectType.empty());
|
||||
|
||||
addProperty("isa", objectType, "", kSettingsNoQuote | kSettingsNoValue);
|
||||
}
|
||||
virtual ~Object() {}
|
||||
|
||||
// Add a simple Property with just a name and a value
|
||||
void addProperty(std::string propName, std::string propValue, std::string propComment = "", int propFlags = 0, int propIndent = 0) {
|
||||
_properties[propName] = Property(propValue, "", propComment, propFlags, propIndent);
|
||||
}
|
||||
|
||||
std::string toString(int flags = 0) {
|
||||
std::string output;
|
||||
output = "\t\t" + _parent->getHash(_id) + (_comment.empty() ? "" : " /* " + _comment + " */") + " = {";
|
||||
|
||||
if (flags & kSettingsAsList)
|
||||
output += "\n";
|
||||
|
||||
// Special case: always output the isa property first
|
||||
output += _parent->writeProperty("isa", _properties["isa"], flags);
|
||||
|
||||
// Write each property
|
||||
for (PropertyList::iterator property = _properties.begin(); property != _properties.end(); ++property) {
|
||||
if (property->first == "isa")
|
||||
continue;
|
||||
|
||||
output += _parent->writeProperty(property->first, property->second, flags);
|
||||
}
|
||||
|
||||
if (flags & kSettingsAsList)
|
||||
output += "\t\t";
|
||||
|
||||
output += "};\n";
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Slight hack, to allow Group access to parent.
|
||||
protected:
|
||||
XcodeProvider *_parent;
|
||||
private:
|
||||
// Returns the type property (should always be the first in the properties map)
|
||||
std::string getType() {
|
||||
assert(!_properties.empty());
|
||||
assert(!_properties["isa"]._settings.empty());
|
||||
|
||||
SettingList::iterator it = _properties["isa"]._settings.begin();
|
||||
|
||||
return it->first;
|
||||
}
|
||||
};
|
||||
|
||||
struct ObjectList {
|
||||
private:
|
||||
std::map<std::string, bool> _objectMap;
|
||||
|
||||
public:
|
||||
std::vector<Object *> _objects;
|
||||
std::string _comment;
|
||||
int _flags = 0;
|
||||
|
||||
~ObjectList() {
|
||||
for (Object *obj : _objects) {
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void add(Object *obj) {
|
||||
std::map<std::string, bool>::iterator it = _objectMap.find(obj->_id);
|
||||
if (it != _objectMap.end() && it->second == true) {
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
|
||||
_objects.push_back(obj);
|
||||
_objectMap[obj->_id] = true;
|
||||
}
|
||||
|
||||
Object *find(std::string id) {
|
||||
for (std::vector<Object *>::iterator it = _objects.begin(); it != _objects.end(); ++it) {
|
||||
if ((*it)->_id == id) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string toString() {
|
||||
std::string output;
|
||||
|
||||
if (!_comment.empty())
|
||||
output = "\n/* Begin " + _comment + " section */\n";
|
||||
|
||||
for (std::vector<Object *>::iterator object = _objects.begin(); object != _objects.end(); ++object)
|
||||
output += (*object)->toString(_flags);
|
||||
|
||||
if (!_comment.empty())
|
||||
output += "/* End " + _comment + " section */\n";
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
// A class to maintain a folder-reference group-hierarchy, which together with the functionality below
|
||||
// allows for breaking up sub-paths into a chain of groups. This helps with merging engines into the
|
||||
// overall group-layout.
|
||||
class Group : public Object {
|
||||
int _childOrder;
|
||||
std::map<std::string, Group *> _childGroups;
|
||||
std::string _treeName;
|
||||
void addChildInternal(const std::string &id, const std::string &comment);
|
||||
public:
|
||||
Group(XcodeProvider *objectParent, const std::string &groupName, const std::string &uniqueName, const std::string &path);
|
||||
void addChildFile(const std::string &name);
|
||||
void addChildByHash(const std::string &hash, const std::string &name);
|
||||
// Should be passed the hash for the entry
|
||||
void addChildGroup(const Group *group);
|
||||
void ensureChildExists(const std::string &name);
|
||||
Group *getChildGroup(const std::string &name);
|
||||
std::string getHashRef() const { return _parent->getHash(_id); }
|
||||
};
|
||||
|
||||
// The path used by the root-source group
|
||||
std::string _projectRoot;
|
||||
// The base source group, currently also re-purposed for containing the various support-groups.
|
||||
Group *_rootSourceGroup;
|
||||
// Helper function to create the chain of groups for the various subfolders. Necessary as
|
||||
// create_project likes to start in engines/
|
||||
Group *touchGroupsForPath(const std::string &path);
|
||||
// Functionality for adding file-refs and build-files, as Group-objects need to be able to do this.
|
||||
void addFileReference(const std::string &id, const std::string &name, FileProperty properties);
|
||||
void addProductFileReference(const std::string &id, const std::string &name);
|
||||
void addBuildFile(const std::string &id, const std::string &name, const std::string &fileRefId, const std::string &comment);
|
||||
// All objects
|
||||
std::map<std::string, std::string> _hashDictionnary;
|
||||
ValueList _defines;
|
||||
|
||||
// Targets
|
||||
ValueList _targets;
|
||||
|
||||
// Lists of objects
|
||||
ObjectList _buildFile;
|
||||
ObjectList _copyFilesBuildPhase;
|
||||
ObjectList _fileReference;
|
||||
ObjectList _frameworksBuildPhase;
|
||||
ObjectList _groups;
|
||||
ObjectList _nativeTarget;
|
||||
ObjectList _project;
|
||||
ObjectList _resourcesBuildPhase;
|
||||
ObjectList _sourcesBuildPhase;
|
||||
ObjectList _buildConfiguration;
|
||||
ObjectList _configurationList;
|
||||
|
||||
void outputMainProjectFile(const BuildSetup &setup);
|
||||
|
||||
// Setup objects
|
||||
void setupCopyFilesBuildPhase();
|
||||
void setupFrameworksBuildPhase(const BuildSetup &setup);
|
||||
void setupNativeTarget();
|
||||
void setupProject();
|
||||
void setupResourcesBuildPhase(const BuildSetup &setup);
|
||||
void setupSourcesBuildPhase();
|
||||
void setupBuildConfiguration(const BuildSetup &setup);
|
||||
void setupImageAssetCatalog(const BuildSetup &setup);
|
||||
void setupAdditionalSources(std::string targetName, Property &files, int &order);
|
||||
|
||||
// Misc
|
||||
void setupDefines(const BuildSetup &setup); // Setup the list of defines to be used on build configurations
|
||||
|
||||
// Retrieve information
|
||||
ValueList& getResourceFiles(const BuildSetup &setup) const;
|
||||
std::string getLibString(std::string libName, bool xcframework) const;
|
||||
|
||||
// Hash generation
|
||||
std::string getHash(std::string key);
|
||||
#ifdef MACOSX
|
||||
std::string md5(std::string key);
|
||||
#endif
|
||||
std::string newHash() const;
|
||||
|
||||
// Output
|
||||
std::string writeProperty(const std::string &variable, Property &property, int flags = 0) const;
|
||||
std::string writeSetting(const std::string &variable, std::string name, std::string comment = "", int flags = 0, int indent = 0) const;
|
||||
std::string writeSetting(const std::string &variable, const Setting &setting) const;
|
||||
};
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_XCODE_H
|
||||
@@ -0,0 +1,275 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
076583601D660492006CBB9B /* cmake.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0765835E1D660492006CBB9B /* cmake.cpp */; };
|
||||
F9A66C691396D4DF00CEE494 /* codeblocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9A66C5F1396D4DF00CEE494 /* codeblocks.cpp */; };
|
||||
F9A66C6A1396D4DF00CEE494 /* create_project.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9A66C621396D4DF00CEE494 /* create_project.cpp */; };
|
||||
F9A66C6B1396D4DF00CEE494 /* msbuild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9A66C651396D4DF00CEE494 /* msbuild.cpp */; };
|
||||
F9A66C6C1396D4DF00CEE494 /* msvc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9A66C671396D4DF00CEE494 /* msvc.cpp */; };
|
||||
F9A66C871396E2F500CEE494 /* xcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9A66C861396E2F500CEE494 /* xcode.cpp */; };
|
||||
F9A66C91139704A400CEE494 /* create_project in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9A66C271396D36100CEE494 /* create_project */; };
|
||||
F9BA99141398064E00C276C2 /* create_project in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9A66C271396D36100CEE494 /* create_project */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
F9A66C251396D36100CEE494 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 12;
|
||||
dstPath = ../../../../../dists/ios7;
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
F9A66C91139704A400CEE494 /* create_project in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F9BA99131398063A00C276C2 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = ../../../../../dists/macosx;
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
F9BA99141398064E00C276C2 /* create_project in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0765835E1D660492006CBB9B /* cmake.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cmake.cpp; path = ../cmake.cpp; sourceTree = "<group>"; };
|
||||
0765835F1D660492006CBB9B /* cmake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmake.h; path = ../cmake.h; sourceTree = "<group>"; };
|
||||
F9A66C271396D36100CEE494 /* create_project */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = create_project; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F9A66C491396D47500CEE494 /* installer.vbs */ = {isa = PBXFileReference; lastKnownFileType = text; name = installer.vbs; path = ../scripts/installer.vbs; sourceTree = "<group>"; };
|
||||
F9A66C4A1396D47500CEE494 /* postbuild.cmd */ = {isa = PBXFileReference; lastKnownFileType = text; name = postbuild.cmd; path = ../scripts/postbuild.cmd; sourceTree = "<group>"; };
|
||||
F9A66C4B1396D47500CEE494 /* prebuild.cmd */ = {isa = PBXFileReference; lastKnownFileType = text; name = prebuild.cmd; path = ../scripts/prebuild.cmd; sourceTree = "<group>"; };
|
||||
F9A66C4C1396D47500CEE494 /* revision.vbs */ = {isa = PBXFileReference; lastKnownFileType = text; name = revision.vbs; path = ../scripts/revision.vbs; sourceTree = "<group>"; };
|
||||
F9A66C5F1396D4DF00CEE494 /* codeblocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = codeblocks.cpp; path = ../codeblocks.cpp; sourceTree = "<group>"; };
|
||||
F9A66C601396D4DF00CEE494 /* codeblocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = codeblocks.h; path = ../codeblocks.h; sourceTree = "<group>"; };
|
||||
F9A66C611396D4DF00CEE494 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../config.h; sourceTree = "<group>"; };
|
||||
F9A66C621396D4DF00CEE494 /* create_project.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = create_project.cpp; path = ../create_project.cpp; sourceTree = "<group>"; };
|
||||
F9A66C631396D4DF00CEE494 /* create_project.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = create_project.h; path = ../create_project.h; sourceTree = "<group>"; };
|
||||
F9A66C641396D4DF00CEE494 /* module.mk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = module.mk; path = ../module.mk; sourceTree = "<group>"; };
|
||||
F9A66C651396D4DF00CEE494 /* msbuild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = msbuild.cpp; path = ../msbuild.cpp; sourceTree = "<group>"; };
|
||||
F9A66C661396D4DF00CEE494 /* msbuild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = msbuild.h; path = ../msbuild.h; sourceTree = "<group>"; };
|
||||
F9A66C671396D4DF00CEE494 /* msvc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = msvc.cpp; path = ../msvc.cpp; sourceTree = "<group>"; };
|
||||
F9A66C681396D4DF00CEE494 /* msvc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = msvc.h; path = ../msvc.h; sourceTree = "<group>"; };
|
||||
F9A66C841396E2D800CEE494 /* xcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xcode.h; path = ../xcode.h; sourceTree = "<group>"; };
|
||||
F9A66C861396E2F500CEE494 /* xcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xcode.cpp; path = ../xcode.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
F9A66C241396D36100CEE494 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
F9A66C1C1396D36100CEE494 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0765835E1D660492006CBB9B /* cmake.cpp */,
|
||||
0765835F1D660492006CBB9B /* cmake.h */,
|
||||
F9A66C861396E2F500CEE494 /* xcode.cpp */,
|
||||
F9A66C841396E2D800CEE494 /* xcode.h */,
|
||||
F9A66C5F1396D4DF00CEE494 /* codeblocks.cpp */,
|
||||
F9A66C601396D4DF00CEE494 /* codeblocks.h */,
|
||||
F9A66C611396D4DF00CEE494 /* config.h */,
|
||||
F9A66C621396D4DF00CEE494 /* create_project.cpp */,
|
||||
F9A66C631396D4DF00CEE494 /* create_project.h */,
|
||||
F9A66C641396D4DF00CEE494 /* module.mk */,
|
||||
F9A66C651396D4DF00CEE494 /* msbuild.cpp */,
|
||||
F9A66C661396D4DF00CEE494 /* msbuild.h */,
|
||||
F9A66C671396D4DF00CEE494 /* msvc.cpp */,
|
||||
F9A66C681396D4DF00CEE494 /* msvc.h */,
|
||||
F9A66C481396D45D00CEE494 /* Scripts */,
|
||||
F9A66C281396D36100CEE494 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F9A66C281396D36100CEE494 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9A66C271396D36100CEE494 /* create_project */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F9A66C481396D45D00CEE494 /* Scripts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9A66C491396D47500CEE494 /* installer.vbs */,
|
||||
F9A66C4A1396D47500CEE494 /* postbuild.cmd */,
|
||||
F9A66C4B1396D47500CEE494 /* prebuild.cmd */,
|
||||
F9A66C4C1396D47500CEE494 /* revision.vbs */,
|
||||
);
|
||||
name = Scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
F9A66C261396D36100CEE494 /* create_project */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F9A66C301396D36100CEE494 /* Build configuration list for PBXNativeTarget "create_project" */;
|
||||
buildPhases = (
|
||||
F9A66C231396D36100CEE494 /* Sources */,
|
||||
F9A66C241396D36100CEE494 /* Frameworks */,
|
||||
F9A66C251396D36100CEE494 /* CopyFiles */,
|
||||
F9BA99131398063A00C276C2 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = create_project;
|
||||
productName = create_project;
|
||||
productReference = F9A66C271396D36100CEE494 /* create_project */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
F9A66C1E1396D36100CEE494 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0720;
|
||||
};
|
||||
buildConfigurationList = F9A66C211396D36100CEE494 /* Build configuration list for PBXProject "create_project" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = F9A66C1C1396D36100CEE494;
|
||||
productRefGroup = F9A66C281396D36100CEE494 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
F9A66C261396D36100CEE494 /* create_project */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
F9A66C231396D36100CEE494 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F9A66C691396D4DF00CEE494 /* codeblocks.cpp in Sources */,
|
||||
F9A66C6A1396D4DF00CEE494 /* create_project.cpp in Sources */,
|
||||
F9A66C6B1396D4DF00CEE494 /* msbuild.cpp in Sources */,
|
||||
F9A66C6C1396D4DF00CEE494 /* msvc.cpp in Sources */,
|
||||
076583601D660492006CBB9B /* cmake.cpp in Sources */,
|
||||
F9A66C871396E2F500CEE494 /* xcode.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
F9A66C2E1396D36100CEE494 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD="c++11";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
POSIX,
|
||||
MACOSX,
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.5;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F9A66C2F1396D36100CEE494 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD="c++11";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
POSIX,
|
||||
MACOSX,
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.5;
|
||||
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F9A66C311396D36100CEE494 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
DEBUG,
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F9A66C321396D36100CEE494 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
F9A66C211396D36100CEE494 /* Build configuration list for PBXProject "create_project" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F9A66C2E1396D36100CEE494 /* Debug */,
|
||||
F9A66C2F1396D36100CEE494 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F9A66C301396D36100CEE494 /* Build configuration list for PBXNativeTarget "create_project" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F9A66C311396D36100CEE494 /* Debug */,
|
||||
F9A66C321396D36100CEE494 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = F9A66C1E1396D36100CEE494 /* Project object */;
|
||||
}
|
||||
Reference in New Issue
Block a user