Add enums and some cleanup (#148)

* support enums

* better compiler warnings

* tweaks to build with clang
This commit is contained in:
water111
2020-12-02 19:51:42 -05:00
committed by GitHub
parent 71dda76e2b
commit ea479bee98
24 changed files with 257 additions and 182 deletions
+5 -5
View File
@@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 17)
# Set default compile flags for GCC
# optimization level can be set here. Note that game/ overwrites this for building game C++ code.
if (CMAKE_COMPILER_IS_GNUCXX)
if (UNIX)
message(STATUS "GCC detected, adding compile flags")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
@@ -17,10 +17,10 @@ if (CMAKE_COMPILER_IS_GNUCXX)
-Winit-self \
-ggdb \
-Wextra \
-Wcast-align \
-Wno-cast-align \
-Wcast-qual \
-Wdisabled-optimization \
-Wformat=2 \
-Wformat \
-Wmissing-include-dirs \
-Woverloaded-virtual \
-Wredundant-decls \
@@ -29,7 +29,7 @@ if (CMAKE_COMPILER_IS_GNUCXX)
else ()
set(CMAKE_CXX_FLAGS "/EHsc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000")
endif (CMAKE_COMPILER_IS_GNUCXX)
endif (UNIX)
IF (WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
@@ -41,7 +41,7 @@ ENDIF ()
option(CODE_COVERAGE "Enable Code Coverage Compiler Flags" OFF)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/third-party/cmake/modules/)
if(CMAKE_COMPILER_IS_GNUCXX AND CODE_COVERAGE)
if(UNIX AND CODE_COVERAGE)
include(CodeCoverage)
append_coverage_compiler_flags()
message("Code Coverage build is enabled!")
+1
View File
@@ -27,6 +27,7 @@ class IR {
virtual TP_Type get_expression_type(const TypeState& input,
const LinkedObjectFile& file,
DecompilerTypeSystem& dts);
virtual ~IR() = default;
};
class IR_Atomic : public virtual IR {
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
class ObjectFileData;
struct ObjectFileData;
struct TPageResultStats {
int total_textures = 0;
+8 -8
View File
@@ -3,18 +3,18 @@ set(CMAKE_CXX_STANDARD 17)
# Set default compile flags for GCC
# optimization level can be set here. Note that game/ overwrites this for building game C++ code.
if(CMAKE_COMPILER_IS_GNUCXX)
if(UNIX)
message(STATUS "GCC detected, adding compile flags")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
-ggdb \
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
-Wall \
-Winit-self \
-Winit-self \
-ggdb \
-Wextra \
-Wcast-align \
-Wno-cast-align \
-Wcast-qual \
-Wdisabled-optimization \
-Wformat=2 \
-Wformat \
-Wmissing-include-dirs \
-Woverloaded-virtual \
-Wredundant-decls \
@@ -22,7 +22,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
-Wsign-promo")
else()
set(CMAKE_CXX_FLAGS "/EHsc")
endif(CMAKE_COMPILER_IS_GNUCXX)
endif(UNIX)
enable_language(ASM_NASM)
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} asm)
-2
View File
@@ -49,8 +49,6 @@ class SystemThread {
Timer stats_timer;
Timer stat_diff_timer;
double cpu_user = 0, cpu_kernel = 0;
uint64_t last_cpu_user = 0, last_cpu_kernel = 0;
uint64_t last_collection_nanoseconds = 0;
int id = -1;
bool want_exit = false;
bool running = false;
+31 -1
View File
@@ -54,8 +54,38 @@
;; ENUMS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; todo, processs mask
; bitfield enum to indicate proprties about a process-tree
(defenum process-mask :bitfield #t :type int32
(execute 0) ; 1
(draw 1) ; 2
(pause 2) ; 4
(menu 3) ; 8
(progress 4) ; 16
(actor-pause 5) ; 32
(sleep 6) ; 64
(sleep-code 7) ; 128
(process-tree 8) ; 256 ; not an actual process, just a "tree node" for organization
(heap-shrunk 9) ; 512
(going 10) ; 1024
(movie 11) ; 2048
(movie-subject 12) ; 4096
(target 13) ; 8192
(sidekick 14) ; 16384
(crate 15) ; 32768
(collectable 16) ; 65536
(enemy 17) ; 131072
(camera 18) ; 262144
(platform 19) ; 524288
(ambient 20) ; 1048576
(entity 21) ; 2097152
(projectile 22) ; 4194304
(attackable 23) ; 8388608
(death 24) ; 16777216
)
;; -961
(defconstant PROCESS_CLEAR_MASK
(lognot (process-mask sleep sleep-code process-tree heap-shrunk)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MACROS
-1
View File
@@ -29,7 +29,6 @@ add_library(compiler
data_compiler/game_count.cpp
debugger/Debugger.cpp
debugger/DebugInfo.cpp
logger/Logger.cpp
listener/Listener.cpp
listener/MemoryMap.cpp
regalloc/IRegister.cpp
+4 -29
View File
@@ -1,5 +1,4 @@
#include "Compiler.h"
#include "goalc/logger/Logger.h"
#include "common/link_types.h"
#include "IR.h"
#include "goalc/regalloc/allocate.h"
@@ -11,8 +10,6 @@
using namespace goos;
Compiler::Compiler() : m_debugger(&m_listener) {
init_logger();
init_settings();
m_listener.add_debugger(&m_debugger);
m_ts.add_builtin_types();
m_global_env = std::make_unique<GlobalEnv>();
@@ -61,36 +58,19 @@ void Compiler::execute_repl() {
if (m_listener.is_connected()) {
m_listener.send_code(data);
if (!m_listener.most_recent_send_was_acked()) {
gLogger.log(MSG_ERR, "Runtime is not responding. Did it crash?\n");
print_compiler_warning("Runtime is not responding. Did it crash?\n");
}
}
}
} catch (std::exception& e) {
gLogger.log(MSG_WARN, "REPL Error: %s\n", e.what());
print_compiler_warning("REPL Error: %s\n", e.what());
}
}
m_listener.disconnect();
}
Compiler::~Compiler() {
gLogger.close();
}
void Compiler::init_logger() {
gLogger.set_file("compiler.txt"); // todo, a better file than this...
gLogger.config[MSG_COLOR].kind = LOG_FILE;
gLogger.config[MSG_DEBUG].kind = LOG_IGNORE;
gLogger.config[MSG_TGT].color = COLOR_GREEN;
gLogger.config[MSG_TGT_INFO].color = COLOR_BLUE;
gLogger.config[MSG_WARN].color = COLOR_RED;
gLogger.config[MSG_ICE].color = COLOR_RED;
gLogger.config[MSG_ERR].color = COLOR_RED;
}
void Compiler::init_settings() {}
FileEnv* Compiler::compile_object_file(const std::string& name,
goos::Object code,
bool allow_emit) {
@@ -169,11 +149,6 @@ Val* Compiler::compile_error_guard(const goos::Object& code, Env* env) {
}
}
void Compiler::ice(const std::string& error) {
gLogger.log(MSG_ICE, "[ICE] %s\n", error.c_str());
throw std::runtime_error("ICE");
}
void Compiler::color_object_file(FileEnv* env) {
for (auto& f : env->functions()) {
AllocationInput input;
@@ -232,7 +207,7 @@ std::vector<std::string> Compiler::run_test_from_file(const std::string& source_
m_listener.record_messages(ListenerMessageKind::MSG_PRINT);
m_listener.send_code(data);
if (!m_listener.most_recent_send_was_acked()) {
gLogger.log(MSG_ERR, "Runtime is not responding after sending test code. Did it crash?\n");
print_compiler_warning("Runtime is not responding after sending test code. Did it crash?\n");
}
return m_listener.stop_recording_messages();
} catch (std::exception& e) {
@@ -258,7 +233,7 @@ std::vector<std::string> Compiler::run_test_from_string(const std::string& src,
m_listener.record_messages(ListenerMessageKind::MSG_PRINT);
m_listener.send_code(data);
if (!m_listener.most_recent_send_was_acked()) {
gLogger.log(MSG_ERR, "Runtime is not responding after sending test code. Did it crash?\n");
print_compiler_warning("Runtime is not responding after sending test code. Did it crash?\n");
}
return m_listener.stop_recording_messages();
} catch (std::exception& e) {
+17 -7
View File
@@ -15,13 +15,13 @@
#include "third-party/fmt/core.h"
#include "third-party/fmt/color.h"
#include "CompilerException.h"
#include "Enum.h"
enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID };
class Compiler {
public:
Compiler();
~Compiler();
void execute_repl();
goos::Interpreter& get_goos() { return m_goos; }
FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit);
@@ -30,9 +30,7 @@ class Compiler {
Env* env);
Val* compile(const goos::Object& code, Env* env);
Val* compile_error_guard(const goos::Object& code, Env* env);
void ice(const std::string& err);
None* get_none() { return m_none.get(); }
std::vector<std::string> run_test_from_file(const std::string& source_code);
std::vector<std::string> run_test_from_string(const std::string& src,
const std::string& obj_name = "*listener*");
@@ -42,14 +40,10 @@ class Compiler {
void enable_throw_on_redefines() { m_throw_on_define_extern_redefinition = true; }
Debugger& get_debugger() { return m_debugger; }
listener::Listener& listener() { return m_listener; }
void poke_target() { m_listener.send_poke(); }
bool connect_to_target();
private:
void init_logger();
void init_settings();
bool try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest);
void set_bitfield(const goos::Object& form, BitFieldVal* dst, RegVal* src, Env* env);
Val* do_set(const goos::Object& form, Val* dst, RegVal* src, Env* env);
@@ -125,6 +119,7 @@ class Compiler {
Debugger m_debugger;
goos::Interpreter m_goos;
std::unordered_map<std::string, TypeSpec> m_symbol_types;
std::unordered_map<std::string, GoalEnum> m_enums;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> m_global_constants;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, LambdaVal*> m_inlineable_functions;
CompilerSettings m_settings;
@@ -140,6 +135,10 @@ class Compiler {
Val* number_to_binteger(const goos::Object& form, Val* in, Env* env);
Val* to_math_type(const goos::Object& form, Val* in, MathMode mode, Env* env);
bool is_none(Val* in);
Val* compile_enum_lookup(const goos::Object& form,
const GoalEnum& e,
const goos::Object& rest,
Env* env);
Val* compile_variable_shift(const goos::Object& form,
const RegVal* in,
@@ -200,6 +199,16 @@ class Compiler {
throw CompilerException("Compilation Error");
}
template <typename... Args>
void print_compiler_warning(const std::string& str, Args&&... args) {
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "[Warning] ");
if (!str.empty() && str.back() == '\n') {
fmt::print(str, std::forward<Args>(args)...);
} else {
fmt::print(str + '\n', std::forward<Args>(args)...);
}
}
public:
// Atoms
@@ -295,6 +304,7 @@ class Compiler {
Val* compile_addr_of(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_declare_type(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_none(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_defenum(const goos::Object& form, const goos::Object& rest, Env* env);
};
#endif // JAK_COMPILER_H
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <string>
#include <unordered_map>
#include "common/common_types.h"
#include "common/type_system/TypeSpec.h"
struct GoalEnum {
TypeSpec base_type;
bool is_bitfield = false;
std::unordered_map<std::string, s64> entries;
bool operator==(const GoalEnum& other) const;
bool operator!=(const GoalEnum& other) const;
};
+1
View File
@@ -20,6 +20,7 @@ class IR {
(void)constraints;
(void)my_id;
}
virtual ~IR() = default;
};
// class IR_Set : public IR {
+1
View File
@@ -21,6 +21,7 @@ class StaticObject {
virtual LoadInfo get_load_info() const = 0;
virtual void generate(emitter::ObjectGenerator* gen) = 0;
virtual int get_addr_offset() const = 0;
virtual ~StaticObject() = default;
emitter::StaticRecord rec;
};
+1
View File
@@ -45,6 +45,7 @@ class Val {
void set_type(TypeSpec ts) { m_ts = std::move(ts); }
bool settable() const { return m_is_settable; }
void mark_as_settable() { m_is_settable = true; }
virtual ~Val() = default;
protected:
TypeSpec m_ts;
+6 -4
View File
@@ -68,7 +68,7 @@ static const std::unordered_map<
// TYPE
{"deftype", &Compiler::compile_deftype},
{"defmethod", &Compiler::compile_defmethod},
// {"defenum", &Compiler::compile_defenum},
{"defenum", &Compiler::compile_defenum},
{"->", &Compiler::compile_deref},
{"&", &Compiler::compile_addr_of},
{"the-as", &Compiler::compile_the_as},
@@ -152,7 +152,7 @@ Val* Compiler::compile(const goos::Object& code, Env* env) {
case goos::ObjectType::FLOAT:
return compile_float(code, env);
default:
ice("Don't know how to compile " + code.print());
throw_compiler_error(code, "Cannot compile {}.", code.print());
}
return get_none();
}
@@ -161,7 +161,6 @@ Val* Compiler::compile(const goos::Object& code, Env* env) {
* Compile a pair/list.
* Can be a compiler form, function call (possibly inlined), method call, immediate application of a
* lambda, or a goos macro.
* TODO - enums.
*/
Val* Compiler::compile_pair(const goos::Object& code, Env* env) {
auto pair = code.as_pair();
@@ -182,7 +181,10 @@ Val* Compiler::compile_pair(const goos::Object& code, Env* env) {
return compile_goos_macro(code, macro_obj, rest, env);
}
// try as an enum (not yet implemented)
auto enum_kv = m_enums.find(head_sym->name);
if (enum_kv != m_enums.end()) {
return compile_enum_lookup(code, enum_kv->second, rest, env);
}
}
// if none of the above cases worked, then treat it like a function/method call.
+2 -5
View File
@@ -4,7 +4,6 @@
*/
#include "goalc/compiler/Compiler.h"
#include "goalc/logger/Logger.h"
/*!
* Define or set a global value. Has some special magic to store data for functions which may be
@@ -73,10 +72,8 @@ Val* Compiler::compile_define_extern(const goos::Object& form, const goos::Objec
"define-extern would redefine the type of symbol {} from {} to {}.",
symbol_string(sym), existing_type->second.print(), new_type.print());
} else {
// todo nicer warning message.
gLogger.log(
MSG_WARN,
"[Warning] define-extern has redefined the type of symbol %s\npreviously: %s\nnow: %s\n",
print_compiler_warning(
"[Warning] define-extern has redefined the type of symbol {}\npreviously: {}\nnow: {}\n",
symbol_string(sym).c_str(), existing_type->second.print().c_str(),
new_type.print().c_str());
}
-1
View File
@@ -4,7 +4,6 @@
*/
#include "goalc/compiler/Compiler.h"
#include "goalc/logger/Logger.h"
#include "third-party/fmt/core.h"
namespace {
+121
View File
@@ -1,6 +1,7 @@
#include "goalc/compiler/Compiler.h"
#include "third-party/fmt/core.h"
#include "common/type_system/deftype.h"
#include "goalc/compiler/Enum.h"
namespace {
@@ -785,4 +786,124 @@ Val* Compiler::compile_none(const goos::Object& form, const goos::Object& rest,
auto args = get_va(form, rest);
va_check(form, args, {}, {});
return get_none();
}
Val* Compiler::compile_defenum(const goos::Object& form, const goos::Object& _rest, Env* env) {
// format is (defenum name [options] [entries])
(void)env;
auto* rest = &_rest;
// name
auto enum_name = symbol_string(pair_car(*rest));
rest = &pair_cdr(*rest);
// default enum type will be int32.
auto enum_type = m_ts.make_typespec("int32");
bool is_bitfield = false;
auto current = pair_car(*rest);
while (current.is_symbol() && symbol_string(current).at(0) == ':') {
auto option_name = symbol_string(current);
rest = &pair_cdr(*rest);
auto option_value = pair_car(*rest);
rest = &pair_cdr(*rest);
current = pair_car(*rest);
if (option_name == ":type") {
enum_type = parse_typespec(option_value);
} else if (option_name == ":bitfield") {
if (symbol_string(option_value) == "#t") {
is_bitfield = true;
} else if (symbol_string(option_value) == "#f") {
is_bitfield = false;
} else {
throw_compiler_error(form, "Invalid option {} to :bitfield option.", option_value.print());
}
} else {
throw_compiler_error(form, "Unknown option {} for defenum.", option_name);
}
}
GoalEnum new_enum;
new_enum.base_type = enum_type;
new_enum.is_bitfield = is_bitfield;
while (!rest->is_empty_list()) {
auto def = pair_car(*rest);
auto name = symbol_string(pair_car(def));
def = pair_cdr(def);
auto value = pair_car(def);
if (!value.is_int()) {
throw_compiler_error(def, "Expected integer for enum value, got {}", value.print());
}
def = pair_cdr(def);
if (!def.is_empty_list()) {
throw_compiler_error(def, "Got too many items in defenum defintion.");
}
new_enum.entries[name] = value.integer_obj.value;
rest = &pair_cdr(*rest);
}
auto existing_kv = m_enums.find(enum_name);
if (existing_kv != m_enums.end() && existing_kv->second != new_enum) {
print_compiler_warning("defenum changes the definition of existing enum {}", enum_name.c_str());
}
m_enums[enum_name] = new_enum;
return get_none();
}
Val* Compiler::compile_enum_lookup(const goos::Object& form,
const GoalEnum& e,
const goos::Object& rest,
Env* env) {
if (e.is_bitfield) {
int64_t value = 0;
for_each_in_list(rest, [&](const goos::Object& o) {
auto kv = e.entries.find(symbol_string(o));
if (kv == e.entries.end()) {
throw_compiler_error(form, "The value {} was not found in enum.", o.print());
}
value |= (1 << kv->second);
});
auto result = compile_integer(value, env);
result->set_type(e.base_type);
return result;
} else {
int64_t value = 0;
bool got = false;
for_each_in_list(rest, [&](const goos::Object& o) {
if (got) {
throw_compiler_error(form, "Invalid enum lookup.");
}
auto kv = e.entries.find(symbol_string(o));
if (kv == e.entries.end()) {
throw_compiler_error(form, "The value {} was not found in enum.", o.print());
}
value = kv->second;
got = true;
});
if (!got) {
throw_compiler_error(form, "Invalid enum lookup.");
}
auto result = compile_integer(value, env);
result->set_type(e.base_type);
return result;
}
return get_none();
}
bool GoalEnum::operator==(const GoalEnum& other) const {
return base_type == other.base_type && is_bitfield == other.is_bitfield &&
entries == other.entries;
}
bool GoalEnum::operator!=(const GoalEnum& other) const {
return !(*this == other);
}
-70
View File
@@ -1,70 +0,0 @@
#include <stdexcept>
#include "Logger.h"
void Logger::close() {
if (fp) {
fclose(fp);
fp = nullptr;
}
}
void Logger::set_file(std::string filename) {
if (fp) {
fclose(fp);
}
fp = fopen(filename.c_str(), "w");
if (!fp) {
throw std::runtime_error("invalid file name " + filename + " in logger");
}
}
void Logger::log(LoggerMessageKind kind, const char* format, ...) {
FILE* dest = nullptr;
auto& settings = config[kind];
switch (settings.kind) {
case LOG_STDERR:
dest = stderr;
break;
case LOG_STDOUT:
dest = stdout;
break;
case LOG_IGNORE:
dest = nullptr;
break;
case LOG_FILE:
dest = fp;
break;
default:
throw std::runtime_error("unknown log destination in log");
}
if (!dest)
return;
if (!settings.prefix.empty()) {
fprintf(dest, "%s", settings.prefix.c_str());
}
if (settings.color != COLOR_NORMAL) {
const char* color_codes[] = {"", "[0;31m", "[0;32m", "[0;36m"};
printf("\033%s", color_codes[settings.color]);
}
va_list arglist;
va_start(arglist, format);
vfprintf(dest, format, arglist);
va_end(arglist);
if (settings.color != COLOR_NORMAL) {
printf("\033[0m");
fflush(stdout);
}
// todo, does this make things slow?
if (settings.kind == LOG_FILE) {
fflush(fp);
}
}
Logger gLogger;
-45
View File
@@ -1,45 +0,0 @@
#pragma once
#ifndef JAK_LOGGER_H
#define JAK_LOGGER_H
#include <string>
#include <cstdarg>
#include <unordered_map>
enum LoggerColor { COLOR_NORMAL, COLOR_RED, COLOR_GREEN, COLOR_BLUE };
enum LoggerDestKind { LOG_STDOUT, LOG_STDERR, LOG_FILE, LOG_IGNORE };
struct LoggerDest {
LoggerDestKind kind = LOG_STDOUT;
LoggerColor color = COLOR_NORMAL;
std::string prefix;
};
enum LoggerMessageKind {
MSG_GOAL,
MSG_ICE,
MSG_ERR,
MSG_COLOR,
MSG_EMIT,
MSG_DEBUG,
MSG_WARN,
MSG_TGT,
MSG_TGT_INFO,
};
class Logger {
public:
void set_file(std::string filename);
void log(LoggerMessageKind kind, const char* format, ...);
std::unordered_map<LoggerMessageKind, LoggerDest> config;
void close();
private:
FILE* fp = nullptr;
};
extern Logger gLogger;
#endif // JAK_LOGGER_H
+1 -1
View File
@@ -30,7 +30,7 @@ ELSE()
target_link_libraries(goalc-test cross_sockets goos common_util runtime compiler type_system gtest Zydis)
ENDIF()
if(CMAKE_COMPILER_IS_GNUCXX AND CODE_COVERAGE)
if(UNIX AND CODE_COVERAGE)
include(CodeCoverage)
append_coverage_compiler_flags()
setup_target_for_coverage_lcov(NAME goalc-test_coverage
@@ -0,0 +1,16 @@
(defenum test-bitfield :bitfield #t
(four 2)
(one 0)
(two 1)
)
(deftype type-with-bitfield (basic)
((name basic)
(thing int32)
)
)
(let ((obj (new 'global 'type-with-bitfield)))
(set! (-> obj thing) (test-bitfield one four))
(the uint (-> obj thing))
)
@@ -0,0 +1,19 @@
(defenum test-int-enum :bitfield #f
(four 4)
(one 1)
(seven 7)
(two 2)
)
(deftype type-with-bitfield2 (basic)
((name basic)
(thing1 int32)
(thing2 int32)
)
)
(let ((obj (new 'global 'type-with-bitfield2)))
(set! (-> obj thing1) (test-int-enum four))
(set! (-> obj thing2) (test-int-enum seven))
(+ (-> obj thing1) (-> obj thing2))
)
+5
View File
@@ -72,4 +72,9 @@ TEST_F(VariableTests, Let) {
TEST_F(VariableTests, StackVars) {
runner.run_static_test(env, testCategory, "stack-ints.gc", {"12\n"});
runner.run_static_test(env, testCategory, "stack-ints-2.gc", {"1\n"});
}
TEST_F(VariableTests, Bitfields) {
runner.run_static_test(env, testCategory, "bitfield-enums.gc", {"5\n"});
runner.run_static_test(env, testCategory, "integer-enums.gc", {"11\n"});
}
+2 -2
View File
@@ -1,8 +1,8 @@
if (CMAKE_COMPILER_IS_GNUCXX)
if (UNIX)
set(CMAKE_CXX_FLAGS "-O3")
else ()
set(CMAKE_CXX_FLAGS "/EHsc")
endif (CMAKE_COMPILER_IS_GNUCXX)
endif (UNIX)
include_directories(../)
add_library(fmt SHARED format.cc)