Compare commits
2 Commits
70375af068
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
3b98f77c08
|
|||
|
959d0a7773
|
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
[submodule "furdb/deps/isocline"]
|
[submodule "deps/isocline"]
|
||||||
path = furdb/deps/isocline
|
path = deps/isocline
|
||||||
url = https://github.com/daanx/isocline
|
url = https://github.com/daanx/isocline
|
||||||
|
|||||||
+10
-6
@@ -11,12 +11,16 @@ find_package(Doxygen)
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_subdirectory(furlang)
|
add_subdirectory(src/furlang)
|
||||||
add_subdirectory(furvm)
|
add_subdirectory(src/furvm)
|
||||||
add_subdirectory(furc)
|
add_subdirectory(src/furc)
|
||||||
add_subdirectory(furas)
|
add_subdirectory(src/furas)
|
||||||
add_subdirectory(disfuras)
|
add_subdirectory(src/disfuras)
|
||||||
add_subdirectory(furdb)
|
add_subdirectory(src/furdb)
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
set(IC_USE_CXX ON)
|
||||||
|
add_subdirectory(${CMAKE_SOURCE_DIR}/deps/isocline)
|
||||||
|
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs)
|
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs)
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
file(GLOB_RECURSE DISFURAS_SRCS "src/**.cpp")
|
|
||||||
file(GLOB_RECURSE DISFURAS_HDRS "include/**.hpp")
|
|
||||||
add_executable(disfuras ${DISFURAS_SRCS} ${DISFURAS_HDRS})
|
|
||||||
target_include_directories(disfuras PRIVATE include/)
|
|
||||||
target_link_libraries(disfuras PUBLIC furlang libfurc libfurvm)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
file(GLOB_RECURSE FURAS_SRCS "src/**.cpp")
|
|
||||||
file(GLOB_RECURSE FURAS_HDRS "include/**.hpp")
|
|
||||||
add_executable(furas ${FURAS_SRCS} ${FURAS_HDRS})
|
|
||||||
target_include_directories(furas PUBLIC include/)
|
|
||||||
target_link_libraries(furas PRIVATE furlang libfurvm)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
set(IC_USE_CXX ON)
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/deps/isocline)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE FURDB_SRCS "src/**.cpp")
|
|
||||||
file(GLOB_RECURSE FURDB_HDRS "include/**.hpp")
|
|
||||||
add_executable(furdb ${FURDB_SRCS} ${FURDB_HDRS})
|
|
||||||
target_include_directories(furdb PRIVATE include/)
|
|
||||||
target_link_libraries(furdb PUBLIC furlang libfurc libfurvm isocline)
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
file(GLOB_RECURSE FURLANG_SRCS "src/**.cpp")
|
|
||||||
file(GLOB_RECURSE FURLANG_HDRS "include/**.hpp")
|
|
||||||
add_library(furlang STATIC ${FURLANG_SRCS} ${FURLANG_HDRS})
|
|
||||||
target_include_directories(furlang PUBLIC include/)
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef FURC_BACK_FURVM_HPP
|
||||||
|
#define FURC_BACK_FURVM_HPP
|
||||||
|
|
||||||
|
#include "furc/middle/ir.hpp"
|
||||||
|
#include "furvm/module.hpp"
|
||||||
|
|
||||||
|
namespace furc {
|
||||||
|
|
||||||
|
class furvm_generator final {
|
||||||
|
public:
|
||||||
|
static furvm::mod generate(const ir_module& mod);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace furc
|
||||||
|
|
||||||
|
#endif // FURC_BACK_FURVM_HPP
|
||||||
@@ -34,6 +34,16 @@ struct ir_operand {
|
|||||||
struct register_s {
|
struct register_s {
|
||||||
std::uint64_t name : 54;
|
std::uint64_t name : 54;
|
||||||
std::uint64_t ver : 10;
|
std::uint64_t ver : 10;
|
||||||
|
|
||||||
|
register_s() = default;
|
||||||
|
|
||||||
|
register_s(std::uint64_t id)
|
||||||
|
: name((id >> 10) & ((1ULL << 54) - 1)), ver((id >> 0) & ((1 << 10) - 1)) {}
|
||||||
|
|
||||||
|
register_s(std::uint64_t name, std::uint64_t ver)
|
||||||
|
: name(name), ver(ver) {}
|
||||||
|
|
||||||
|
operator std::uint64_t() const { return name << 10 | ver; }
|
||||||
} reg;
|
} reg;
|
||||||
std::uint16_t variable;
|
std::uint16_t variable;
|
||||||
std::uint16_t global;
|
std::uint16_t global;
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* SSA destruction (out-of-SSA phase) for register-based targets based on "Mechanizing Conventional SSA for a
|
||||||
|
* Verified Destruction with Coalescing" by Delphine Demange and Yon Fernandez de Retana
|
||||||
|
* (https://dl.acm.org/doi/pdf/10.1145/2892208.2892222 09/11/2026).
|
||||||
|
*/
|
||||||
|
#ifndef FURC_MIDDLE_REG_GEN_HPP
|
||||||
|
#define FURC_MIDDLE_REG_GEN_HPP
|
||||||
|
|
||||||
|
#include "furc/middle/ir.hpp"
|
||||||
|
#include "furc/middle/ssa.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace furc {
|
||||||
|
|
||||||
|
class reg_gen {
|
||||||
|
public:
|
||||||
|
class disjoint_set {
|
||||||
|
public:
|
||||||
|
std::uint64_t find(std::uint64_t var) {
|
||||||
|
if (m_parents.find(var) == m_parents.end()) m_parents.emplace(var, var);
|
||||||
|
if (m_parents[var] == var) return var;
|
||||||
|
return find(m_parents[var]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unite(std::uint64_t var1, std::uint64_t var2) {
|
||||||
|
std::uint64_t rep1 = find(var1);
|
||||||
|
std::uint64_t rep2 = find(var2);
|
||||||
|
if (rep1 != rep2) m_parents[rep1] = rep2;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::uint64_t, std::uint64_t> m_parents;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
struct block_info {
|
||||||
|
std::unordered_set<std::uint64_t> defs;
|
||||||
|
std::unordered_set<std::uint64_t> uses;
|
||||||
|
std::unordered_set<std::uint64_t> liveIn;
|
||||||
|
std::unordered_set<std::uint64_t> liveOut;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
reg_gen(ir_function& func, ssa& ssa) {
|
||||||
|
std::vector<block_info> lifeBlocks;
|
||||||
|
live_analysis(lifeBlocks, func.blocks, ssa.cfgBlocks);
|
||||||
|
remove_interference(func.blocks, lifeBlocks);
|
||||||
|
merge(func.blocks);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static void live_analysis(std::vector<block_info>& lifeBlocks,
|
||||||
|
const std::vector<ir_basic_block>& irBlocks,
|
||||||
|
const std::vector<ssa::cfg_block>& cfgBlocks) {
|
||||||
|
lifeBlocks.resize(irBlocks.size());
|
||||||
|
for (std::uint64_t i = 0; i < irBlocks.size(); ++i) {
|
||||||
|
const auto& irBlock = irBlocks[i];
|
||||||
|
auto& block = lifeBlocks[i];
|
||||||
|
|
||||||
|
for (const auto& instr : irBlock.instructions) {
|
||||||
|
for (const auto& op : instr.sources) {
|
||||||
|
if (op.type != ir_operand::Register) continue;
|
||||||
|
if (block.defs.find(op.value.reg) != block.defs.end()) continue;
|
||||||
|
block.uses.insert(op.value.reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instr.destination.has_value() || instr.destination->type != ir_operand::Register) continue;
|
||||||
|
block.defs.insert(instr.destination->value.reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = true;
|
||||||
|
while (changed) {
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
for (std::uint64_t i = 0; i < irBlocks.size(); ++i) {
|
||||||
|
const auto& irBlock = irBlocks[i];
|
||||||
|
auto& block = lifeBlocks[i];
|
||||||
|
|
||||||
|
std::unordered_set<std::uint64_t> newSet;
|
||||||
|
for (auto succ : cfgBlocks[i].sucs) {
|
||||||
|
newSet.insert(lifeBlocks[succ].liveIn.begin(), lifeBlocks[succ].liveIn.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSet != block.liveOut) {
|
||||||
|
block.liveOut = newSet;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
newSet.clear();
|
||||||
|
newSet.insert(block.uses.begin(), block.uses.end());
|
||||||
|
for (const auto& var : block.liveOut) {
|
||||||
|
if (block.defs.find(var) != block.defs.end()) continue;
|
||||||
|
newSet.insert(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSet != block.liveIn) {
|
||||||
|
block.liveIn = newSet;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_interference(std::vector<ir_basic_block>& irBlocks, const std::vector<block_info>& lifeBlocks) {
|
||||||
|
for (std::uint64_t i = 0; i < irBlocks.size(); ++i) {
|
||||||
|
auto& irBlock = irBlocks[i];
|
||||||
|
|
||||||
|
for (auto it = irBlock.instructions.begin(), end = irBlock.instructions.end();
|
||||||
|
it != end && it->type == ir_instruction::Phi;
|
||||||
|
++it) {
|
||||||
|
assert(it->destination.has_value() && it->destination->type == ir_operand::Register);
|
||||||
|
const auto& phiDst = it->destination->value.reg;
|
||||||
|
|
||||||
|
for (auto& op : it->sources) {
|
||||||
|
assert(op.type == ir_operand::PhiPair);
|
||||||
|
const auto& predBlock = lifeBlocks[op.value.phiPair.block];
|
||||||
|
auto& phiArg = op.value.phiPair.reg;
|
||||||
|
if (predBlock.liveOut.count(phiArg) == 0 || phiArg == phiDst) continue;
|
||||||
|
|
||||||
|
auto oldArg = phiArg;
|
||||||
|
phiArg.ver = 0; // TODO: Allocate temporary registers
|
||||||
|
|
||||||
|
auto& irBlock = irBlocks[op.value.phiPair.block];
|
||||||
|
assert(!irBlock.instructions.empty());
|
||||||
|
auto it = irBlock.instructions.end() - 1;
|
||||||
|
if (ir_instruction::is_terminating(it->type)) --it;
|
||||||
|
irBlock.instructions.emplace(it,
|
||||||
|
ir_instruction{ ir_instruction::Move,
|
||||||
|
ir_operand::reg(phiArg.name, phiArg.ver),
|
||||||
|
{ ir_operand::reg(oldArg.name, oldArg.ver) } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void merge(std::vector<ir_basic_block>& irBlocks) {
|
||||||
|
disjoint_set dj;
|
||||||
|
|
||||||
|
for (const auto& block : irBlocks) {
|
||||||
|
for (const auto& instr : block.instructions) {
|
||||||
|
if (instr.type != ir_instruction::Phi) break;
|
||||||
|
|
||||||
|
assert(instr.destination.has_value() && instr.destination->type == ir_operand::Register);
|
||||||
|
const auto& phiDst = instr.destination->value.reg;
|
||||||
|
dj.find(phiDst);
|
||||||
|
|
||||||
|
for (const auto& op : instr.sources) {
|
||||||
|
assert(op.type == ir_operand::PhiPair);
|
||||||
|
const auto& predBlock = op.value.phiPair.block;
|
||||||
|
const auto& phiArg = op.value.phiPair.reg;
|
||||||
|
dj.unite(phiDst, phiArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& block : irBlocks) {
|
||||||
|
auto it = block.instructions.begin();
|
||||||
|
while (it != block.instructions.end() && it->type == ir_instruction::Phi) {
|
||||||
|
it = block.instructions.erase(it);
|
||||||
|
}
|
||||||
|
for (; it != block.instructions.end(); ++it) {
|
||||||
|
for (auto& op : it->sources) {
|
||||||
|
if (op.type != ir_operand::Register) continue;
|
||||||
|
op.value.reg = dj.find(op.value.reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!it->destination.has_value() || it->destination->type != ir_operand::Register) continue;
|
||||||
|
it->destination->value.reg = dj.find(it->destination->value.reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace furc
|
||||||
|
|
||||||
|
#endif // FURC_MIDDLE_REG_GEN_HPP
|
||||||
@@ -34,18 +34,18 @@ public:
|
|||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
ssa(ir_function& func) {
|
ssa(ir_function& func) {
|
||||||
m_registers.resize(func.regCount);
|
registers.resize(func.regCount);
|
||||||
compute_cfg(func.blocks, m_cfgBlocks);
|
compute_cfg(func.blocks, cfgBlocks);
|
||||||
collect_registers(func.blocks, m_registers, m_globals);
|
collect_registers(func.blocks, registers, globals);
|
||||||
|
|
||||||
std::vector<std::uint64_t> order;
|
std::vector<std::uint64_t> order;
|
||||||
compute_rpo(m_cfgBlocks, m_ssaBlocks, order);
|
compute_rpo(cfgBlocks, ssaBlocks, order);
|
||||||
|
|
||||||
build_dtree(m_cfgBlocks, m_ssaBlocks, order);
|
build_dtree(cfgBlocks, ssaBlocks, order);
|
||||||
compute_dfrontiers(m_cfgBlocks, m_ssaBlocks);
|
compute_dfrontiers(cfgBlocks, ssaBlocks);
|
||||||
|
|
||||||
ssaification(func.blocks, m_cfgBlocks, m_ssaBlocks, m_registers, m_globals);
|
ssaification(func.blocks, cfgBlocks, ssaBlocks, registers, globals);
|
||||||
rename(func.blocks, func.regCount, m_cfgBlocks, m_ssaBlocks, order);
|
rename(func.blocks, func.regCount, cfgBlocks, ssaBlocks, order);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static void compute_cfg(const std::vector<ir_basic_block>& irBlocks, std::vector<cfg_block>& cfgBlocks);
|
static void compute_cfg(const std::vector<ir_basic_block>& irBlocks, std::vector<cfg_block>& cfgBlocks);
|
||||||
@@ -89,11 +89,11 @@ private:
|
|||||||
const std::vector<cfg_block>& blocks);
|
const std::vector<cfg_block>& blocks);
|
||||||
|
|
||||||
static std::size_t intersect(std::vector<ssa_block>& m_blocks, std::size_t b1, std::size_t b2);
|
static std::size_t intersect(std::vector<ssa_block>& m_blocks, std::size_t b1, std::size_t b2);
|
||||||
private:
|
public:
|
||||||
std::vector<cfg_block> m_cfgBlocks;
|
std::vector<cfg_block> cfgBlocks;
|
||||||
std::vector<ssa_block> m_ssaBlocks;
|
std::vector<ssa_block> ssaBlocks;
|
||||||
std::vector<register_info> m_registers;
|
std::vector<register_info> registers;
|
||||||
std::unordered_set<std::uint64_t> m_globals;
|
std::unordered_set<std::uint64_t> globals;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace furc
|
} // namespace furc
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB_RECURSE DISFURAS_SRCS "${CMAKE_SOURCE_DIR}/src/disfuras/**.cpp")
|
||||||
|
add_executable(disfuras ${DISFURAS_SRCS})
|
||||||
|
target_include_directories(disfuras PRIVATE ${CMAKE_SOURCE_DIR}/include/)
|
||||||
|
target_link_libraries(disfuras PUBLIC furlang libfurc libfurvm)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
file(GLOB_RECURSE FURAS_SRCS "${CMAKE_SOURCE_DIR}/src/furas/**.cpp")
|
||||||
|
file(GLOB_RECURSE FURAS_HDRS "${CMAKE_SOURCE_DIR}/include/furas/**.hpp")
|
||||||
|
add_executable(furas ${FURAS_SRCS} ${FURAS_HDRS})
|
||||||
|
target_include_directories(furas PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||||
|
target_link_libraries(furas PRIVATE furlang libfurvm)
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
file(GLOB_RECURSE FURC_SRCS "src/**.cpp")
|
file(GLOB_RECURSE FURC_SRCS "${CMAKE_SOURCE_DIR}/src/furc/**.cpp")
|
||||||
file(GLOB_RECURSE FURC_HDRS "include/**.hpp")
|
file(GLOB_RECURSE FURC_HDRS "${CMAKE_SOURCE_DIR}/include/furc/**.hpp")
|
||||||
add_library(libfurc ${FURC_SRCS} ${FURC_HDRS})
|
add_library(libfurc ${FURC_SRCS} ${FURC_HDRS})
|
||||||
target_include_directories(libfurc PUBLIC include/)
|
target_include_directories(libfurc PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||||
target_compile_definitions(libfurc PRIVATE LIBFURC)
|
target_compile_definitions(libfurc PRIVATE LIBFURC)
|
||||||
set_target_properties(libfurc PROPERTIES PREFIX "")
|
set_target_properties(libfurc PROPERTIES PREFIX "")
|
||||||
target_link_libraries(libfurc PUBLIC furlang libfurvm)
|
target_link_libraries(libfurc PUBLIC furlang libfurvm)
|
||||||
add_executable(furc src/main.cpp)
|
add_executable(furc "${CMAKE_SOURCE_DIR}/src/furc/main.cpp")
|
||||||
target_link_libraries(furc PRIVATE libfurc)
|
target_link_libraries(furc PRIVATE libfurc)
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|
||||||
add_executable(furc_tests "test/ssa.cpp")
|
add_executable(furc_tests "${CMAKE_SOURCE_DIR}/test/furc/ssa.cpp")
|
||||||
target_link_libraries(furc_tests PRIVATE libfurc GTest::gtest_main)
|
target_link_libraries(furc_tests PRIVATE libfurc GTest::gtest_main)
|
||||||
gtest_discover_tests(furc_tests)
|
gtest_discover_tests(furc_tests)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include "furc/back/furvm/target.hpp"
|
||||||
|
|
||||||
|
#include "furvm/function.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace furc {
|
||||||
|
|
||||||
|
furvm::mod furvm_generator::generate(const ir_module& mod) {
|
||||||
|
if (!mod.variables.empty()) throw std::runtime_error("global variables are not supported for furvm yet");
|
||||||
|
|
||||||
|
furvm::mod furvmMod;
|
||||||
|
for (const auto& func : mod.functions) {
|
||||||
|
furvmMod.emplace_function(furvm::function_sig{ {}, {} }, furvmMod.bytecode().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return furvmMod;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace furc
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "furc/front/lexer.hpp"
|
#include "furc/front/lexer.hpp"
|
||||||
#include "furc/front/parser.hpp"
|
#include "furc/front/parser.hpp"
|
||||||
#include "furc/middle/ir.hpp"
|
#include "furc/middle/ir.hpp"
|
||||||
|
#include "furc/middle/reg_gen.hpp"
|
||||||
#include "furc/middle/ssa.hpp"
|
#include "furc/middle/ssa.hpp"
|
||||||
#include "furlang/arena.hpp"
|
#include "furlang/arena.hpp"
|
||||||
|
|
||||||
@@ -20,7 +21,8 @@ int main(void) {
|
|||||||
furc::parser parser = { std::move(lexer), arena };
|
furc::parser parser = { std::move(lexer), arena };
|
||||||
furc::ir_module irModule = furc::ir_generator::generate(parser.parse());
|
furc::ir_module irModule = furc::ir_generator::generate(parser.parse());
|
||||||
for (auto& func : irModule.functions) {
|
for (auto& func : irModule.functions) {
|
||||||
furc::ssa ssa(*func);
|
furc::ssa ssa(*func);
|
||||||
|
furc::reg_gen gen(*func, ssa);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
file(GLOB_RECURSE FURDB_SRCS "${CMAKE_SOURCE_DIR}/src/furdb/**.cpp")
|
||||||
|
file(GLOB_RECURSE FURDB_HDRS "${CMAKE_SOURCE_DIR}/include/furdb/**.hpp")
|
||||||
|
add_executable(furdb ${FURDB_SRCS} ${FURDB_HDRS})
|
||||||
|
target_include_directories(furdb PRIVATE ${CMAKE_SOURCE_DIR}/include/)
|
||||||
|
target_link_libraries(furdb PUBLIC furlang libfurc libfurvm isocline)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB_RECURSE FURLANG_SRCS "${CMAKE_SOURCE_DIR}/src/furlang/**.cpp")
|
||||||
|
file(GLOB_RECURSE FURLANG_HDRS "${CMAKE_SOURCE_DIR}/include/furlang/**.hpp")
|
||||||
|
add_library(furlang STATIC ${FURLANG_SRCS} ${FURLANG_HDRS})
|
||||||
|
target_include_directories(furlang PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
file(GLOB_RECURSE FURVM_SRCS "src/**.cpp")
|
file(GLOB_RECURSE FURVM_SRCS "${CMAKE_SOURCE_DIR}/src/furvm/**.cpp")
|
||||||
file(GLOB_RECURSE FURVM_HDRS "include/**.hpp")
|
file(GLOB_RECURSE FURVM_HDRS "${CMAKE_SOURCE_DIR}/include/furvm/**.hpp")
|
||||||
add_library(libfurvm ${FURVM_SRCS} ${FURVM_HDRS})
|
add_library(libfurvm ${FURVM_SRCS} ${FURVM_HDRS})
|
||||||
target_include_directories(libfurvm PUBLIC include/)
|
target_include_directories(libfurvm PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||||
target_compile_definitions(libfurvm PRIVATE LIBFURVM)
|
target_compile_definitions(libfurvm PRIVATE LIBFURVM)
|
||||||
set_target_properties(libfurvm PROPERTIES PREFIX "")
|
set_target_properties(libfurvm PROPERTIES PREFIX "")
|
||||||
target_link_libraries(libfurvm PUBLIC furlang)
|
target_link_libraries(libfurvm PUBLIC furlang)
|
||||||
add_executable(furvm src/main.cpp)
|
add_executable(furvm "${CMAKE_SOURCE_DIR}/src/furvm/main.cpp")
|
||||||
target_link_libraries(furvm PRIVATE libfurvm)
|
target_link_libraries(furvm PRIVATE libfurvm)
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|
||||||
file(GLOB_RECURSE FURVM_TESTS "test/**.cpp")
|
file(GLOB_RECURSE FURVM_TESTS "${CMAKE_SOURCE_DIR}/test/furvm/**.cpp")
|
||||||
add_executable(furvm_tests ${FURVM_TESTS})
|
add_executable(furvm_tests ${FURVM_TESTS})
|
||||||
target_link_libraries(furvm_tests PRIVATE libfurvm GTest::gtest_main)
|
target_link_libraries(furvm_tests PRIVATE libfurvm GTest::gtest_main)
|
||||||
gtest_discover_tests(furvm_tests)
|
gtest_discover_tests(furvm_tests)
|
||||||
Reference in New Issue
Block a user