Skip to content

Commit

Permalink
Enhance tests for embedded compiler usage
Browse files Browse the repository at this point in the history
Re #50 #51
  • Loading branch information
lefticus committed Aug 2, 2022
1 parent edf6463 commit 3590880
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 16 deletions.
12 changes: 7 additions & 5 deletions cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ cmake_policy(SET CMP0087 NEW)

set(src main.cpp simulate.hpp simulate.cpp)

if(ENABLE_MODELICA_COMPILER)
include(embed_jmodelica.cmake)
embed_jmodelica(${jmodelica_path} jmodelica_files jmodelica_paths)
if(ENABLE_COMPILER OR ENABLE_MODELICA_COMPILER)
if(ENABLE_MODELICA_COMPILER)
include(embed_jmodelica.cmake)
embed_jmodelica(${jmodelica_path} jmodelica_files jmodelica_paths)

include(embed_optimica.cmake)
embed_optimica(${optimica_path} optimica_files optimica_paths)
include(embed_optimica.cmake)
embed_optimica(${optimica_path} optimica_files optimica_paths)
endif()

include(embed_libc.cmake)
embed_libc(libc_files libc_paths)
Expand Down
2 changes: 1 addition & 1 deletion cli/compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ int modelicaToFMU(const std::string &moinput,
}

// tmp is where we extract embedded files
const auto &temp_dir = output_dir / "tmp";
const auto temp_dir = output_dir / "tmp";
extractEmbeddedCompilerFiles(temp_dir, moType);

auto jmodelica_dir = temp_dir / "JModelica";
Expand Down
17 changes: 12 additions & 5 deletions compiler/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ namespace spawn {

void Compiler::write_shared_object_file(const spawn_fs::path &loc,
const spawn_fs::path &sysroot,
const std::vector<spawn_fs::path> &additional_libs)
const std::vector<spawn_fs::path> &additional_libs,
bool link_standard_libs)
{
util::Temp_Directory td;
const auto temporary_object_file_location = td.dir() / "temporary_object.o";
Expand All @@ -117,12 +118,18 @@ void Compiler::write_shared_object_file(const spawn_fs::path &loc,
str_args.push_back(toString(lib));
}

if (link_standard_libs) {
str_args.insert(str_args.end(),
{
"-lm",
"-lc",
"-ldl",
"-lpthread",
});
}

str_args.insert(str_args.end(),
{
"-lm",
"-lc",
"-ldl",
"-lpthread",
"-o",
toString(loc),
});
Expand Down
3 changes: 2 additions & 1 deletion compiler/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class Compiler
void write_object_file(const spawn_fs::path &loc);
void write_shared_object_file(const spawn_fs::path &loc,
const spawn_fs::path &sysroot,
const std::vector<spawn_fs::path> &additional_libs = {});
const std::vector<spawn_fs::path> &additional_libs = {},
bool link_standard_libs = true);

private:
std::string m_target_triple{get_target_triple()};
Expand Down
6 changes: 6 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})

add_library(example_fmu_lib MODULE example_fmu_lib.cpp)

if (ENABLE_COMPILER OR ENABLE_MODELICA_COMPILER)
set(EMBEDDED_COMPILER_TESTS test_embedded_compiler.cpp)
endif ()

add_executable(
tests
catch.cpp
Expand All @@ -29,6 +33,7 @@ add_executable(
test_utils.cpp
test_mbl_idf.cpp
test_infiltration.cpp
${EMBEDDED_COMPILER_TESTS}
)

add_dependencies(tests example_fmu_lib)
Expand All @@ -37,6 +42,7 @@ target_link_libraries(tests PRIVATE CONAN_PKG::catch2 spawn_utils fmu libspawn c
if (ENABLE_COMPILER OR ENABLE_MODELICA_COMPILER)
add_executable(test_compiler test_compiler.cpp)
target_link_libraries(test_compiler PRIVATE compile_options compiler)
target_link_libraries(tests PRIVATE compiler)
endif()


Expand Down
143 changes: 143 additions & 0 deletions test/test_embedded_compiler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include "../util/filesystem.hpp"
#include "../util/temp_directory.hpp"
#include "../util/dynamiclibrary.hpp"

#include "../compiler/compiler.hpp"
#include <catch2/catch.hpp>

TEST_CASE("Sanity Test Embedded Compiler")
{
const std::vector<spawn_fs::path> include_paths{};
const std::vector<std::string> flags{};
spawn::Compiler compiler(include_paths, flags);

spawn::util::Temp_Directory td;

const spawn_fs::path test_file_path = td.dir() / "test.c";

{
std::ofstream test_file(test_file_path);
test_file<<"int main() {}" << std::endl; // we want a flush here
}

compiler.compile_and_link(test_file_path);

const spawn_fs::path object_path = td.dir() / "test.so";

compiler.write_shared_object_file(object_path, td.dir(), {}, false);


CHECK(spawn_fs::exists(object_path));
CHECK(spawn_fs::is_regular_file(object_path));

const auto file_size = spawn_fs::file_size(object_path);

CHECK(file_size > 0);
}

TEST_CASE("Test embedded compiler simple loadable module")
{
const std::vector<spawn_fs::path> include_paths{};
const std::vector<std::string> flags{};
spawn::Compiler compiler(include_paths, flags);

spawn::util::Temp_Directory td;

const spawn_fs::path test_file_path = td.dir() / "test.c";

{
std::ofstream test_file(test_file_path);
test_file << "int get_value() { return 42; }" << std::endl; // we want a flush here
}

compiler.compile_and_link(test_file_path);

const spawn_fs::path object_path = td.dir() / "test.so";

compiler.write_shared_object_file(object_path, td.dir(), {}, false);

CHECK(spawn_fs::exists(object_path));
CHECK(spawn_fs::is_regular_file(object_path));

const auto file_size = spawn_fs::file_size(object_path);

CHECK(file_size > 0);

spawn::util::Dynamic_Library dl(object_path);

CHECK_THROWS(dl.load_symbol<void ()>("unknown_symbol"));

const auto func = dl.load_symbol<int ()>("get_value");

CHECK(func() == 42);
}

TEST_CASE("Test embedded compiler simple loadable module with param")
{
const std::vector<spawn_fs::path> include_paths{};
const std::vector<std::string> flags{};
spawn::Compiler compiler(include_paths, flags);

spawn::util::Temp_Directory td;

const spawn_fs::path test_file_path = td.dir() / "test.c";

{
std::ofstream test_file(test_file_path);
test_file << "int get_value_1(int input) { return 42 * input; }" << std::endl; // we want a flush here
}

compiler.compile_and_link(test_file_path);

const spawn_fs::path object_path = td.dir() / "test.so";

compiler.write_shared_object_file(object_path, td.dir(), {}, false);

CHECK(spawn_fs::exists(object_path));
CHECK(spawn_fs::is_regular_file(object_path));

const auto file_size = spawn_fs::file_size(object_path);

CHECK(file_size > 0);

spawn::util::Dynamic_Library dl(object_path);
const auto func = dl.load_symbol<int(int)>("get_value_1");

CHECK(func(4) == 42 * 4);
}

TEST_CASE("Test embedded compiler with loadable module with cmath")
{
const std::vector<spawn_fs::path> include_paths{};
const std::vector<std::string> flags{};
spawn::Compiler compiler(include_paths, flags);

spawn::util::Temp_Directory td;

const spawn_fs::path test_file_path = td.dir() / "test.c";

{
std::ofstream test_file(test_file_path);
// Note: fabs was ruled out because it gets eliminated in the resulting binary
test_file << "#include <math.h>\ndouble get_cos(double input) { return cos(input); }" << std::endl; // we want a flush here
}

compiler.compile_and_link(test_file_path);

const spawn_fs::path object_path = td.dir() / "test.so";

compiler.write_shared_object_file(object_path, td.dir(), {}, false);

CHECK(spawn_fs::exists(object_path));
CHECK(spawn_fs::is_regular_file(object_path));

const auto file_size = spawn_fs::file_size(object_path);

CHECK(file_size > 0);

spawn::util::Dynamic_Library dl(object_path);
const auto func = dl.load_symbol<double (double)>("get_cos");

CHECK(func(-42.0) == std::cos(-42.0));
CHECK(func(42.0) == std::cos(42.0));
}
2 changes: 1 addition & 1 deletion test/test_spawn_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ TEST_CASE("Test two Spawns")
spawn::util::Temp_Directory working_path1{};
spawn::util::Temp_Directory working_path2{};

spawn::Spawn spawn1("spawn1", spawn_input, working_path1.dir());
spawn::Spawn spawn1("spawn1", spawn_input, working_path2.dir());
spawn::Spawn spawn2("spawn2", spawn_input, working_path2.dir());

spawn1.start();
Expand Down
6 changes: 3 additions & 3 deletions util/dynamiclibrary_posix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace util {
template <typename Signature> [[nodiscard]] Signature *load_symbol(const std::string &name)
{
// reinterpret_cast is necessary here
const auto symbol = reinterpret_cast<Signature *>(dlsym(m_handle.get(), name.c_str()));
const auto symbol = reinterpret_cast<Signature *>(dlsym(m_handle.get(), name.c_str())); // NOLINT

if (symbol == nullptr) {
throw std::runtime_error(fmt::format("Unable to load symbol: '{}', reason: '{}'", name, dlerror()));
throw std::runtime_error(fmt::format("Unable to load symbol: '{}', reason: '{}'", name, dlerror())); // NOLINT
}

return symbol;
Expand All @@ -28,7 +28,7 @@ namespace util {
{
if (!m_handle) {
throw std::runtime_error(
fmt::format("Unable to load library '{}', reason: '{}'", m_location.string(), dlerror()));
fmt::format("Unable to load library '{}', reason: '{}'", m_location.string(), dlerror())); // NOLINT
}
}

Expand Down

0 comments on commit 3590880

Please sign in to comment.