diff options
author | Roland Reichwein <mail@reichwein.it> | 2024-05-31 17:04:21 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2024-05-31 17:04:21 +0200 |
commit | 9b6c531505ff74f119bff6facae35c10801b2c6c (patch) | |
tree | e8efa038553588a7f4bde3f3ebe2cc3c996baf73 | |
parent | 92be2196d6515f854295b0b830ad7dd4b97bb956 (diff) |
Link dynamic lib, test
-rw-r--r-- | LanguageSettings.cpp | 7 | ||||
-rw-r--r-- | file.cpp | 16 | ||||
-rw-r--r-- | file.h | 4 | ||||
-rw-r--r-- | test-ymake.cpp | 65 |
4 files changed, 88 insertions, 4 deletions
diff --git a/LanguageSettings.cpp b/LanguageSettings.cpp index 5bec072..9f3feaf 100644 --- a/LanguageSettings.cpp +++ b/LanguageSettings.cpp @@ -75,7 +75,10 @@ std::string LanguageSettings::getLinkCommand(const std::filesystem::path& target const std::vector<std::filesystem::path>& link_libs) const { std::string input_string{std::accumulate(inputs.begin(), inputs.end(), std::string{}, - [](const std::string& sum, const fs::path& p){ return sum + " " + p.string(); })}; + [](const std::string& sum, const fs::path& p){ + if (is_dynamic_lib(p) || is_dynamic_lib_link(p)) { return sum; } + return sum + " " + p.string(); + })}; if (is_static_lib(target)) { // link: $(AR) rcs libxyz.a x.o y.o z.o @@ -93,7 +96,7 @@ std::string LanguageSettings::getLinkCommand(const std::filesystem::path& target if (is_static_lib(i.string())) { input_string += " " + i.string(); } else if (is_dynamic_lib(i.string()) || is_dynamic_lib_link(i.string())) { - input_string += " -L" + i.parent_path().string() + " -l" + dynamic_lib_name(i); + input_string += " -L" + lib_path(i).string() + " -l" + dynamic_lib_name(i); } else { // link external dynamic lib, e.g. "fmt" link_libs_string += " -l" + i.string(); } @@ -100,10 +100,15 @@ std::filesystem::path soname_short(const std::filesystem::path& p) // file1.so.1 -> file1 std::string dynamic_lib_name(const std::filesystem::path& p) { - std::string result {p.stem().string()}; + std::string result {p.filename().string()}; if (result.substr(0, 3) == "lib") { result = result.substr(3); } + size_t dotpos{result.find('.')}; + if (dotpos == std::string::npos) { + throw std::runtime_error("Unexpected path: Expected dot (.) in: "s + p.string()); + } + result = result.substr(0, dotpos); return result; } @@ -120,6 +125,15 @@ std::filesystem::path simplified_path(const std::filesystem::path& p) return p; } +std::filesystem::path lib_path(const std::filesystem::path& p) +{ + fs::path result{p.parent_path()}; + if (result.empty()) { + result = "."; + } + return result; +} + bool is_executable_command(const std::string& file) { std::vector<std::string> paths {Reichwein::Stringhelper::split(env_value("PATH"), ":")}; @@ -19,6 +19,10 @@ std::string dynamic_lib_name(const std::filesystem::path& p); // removes initial "./" std::filesystem::path simplified_path(const std::filesystem::path& p); +// path of lib, i.e. parent +// e.g. libs/libabc.so.1.0.0 -> libs +// e.g. libabc.so -> . +std::filesystem::path lib_path(const std::filesystem::path& p); std::string env_value(const std::string& key); bool is_executable_command(const std::string& file); diff --git a/test-ymake.cpp b/test-ymake.cpp index 8184bcf..cf51a26 100644 --- a/test-ymake.cpp +++ b/test-ymake.cpp @@ -805,8 +805,71 @@ int main(int argc, char* argv[]) EXPECT_TRUE(!fs::exists("runmain")); } +TEST_F(ymakeTest, use_one_dynamic_lib) +{ + create_file("YMakefile", R"( +<ymake> + <build> + <name>libhello.so.1.0.0</name> + <source>hello.cpp</source> + </build> + <build> + <name>runmain</name> + <source>runmain.cpp</source> + <linklib>libhello.so</linklib> + </build> +</ymake> +)"); + + create_file("hello.cpp", R"(#include "hello.h" +#include <iostream> +int hello() +{ + std::cout << "Hello." << std::endl; + return 0; +})"); + + create_file("hello.h", R"(#pragma once +__attribute__((visibility("default"))) int hello(); +)"); + + create_file("runmain.cpp", R"(#include "hello.h" +int main(int argc, char* argv[]) +{ + hello(); + return 0; +})"); + + std::vector<std::string> output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + ASSERT_EQ(output.size(), 6); // compile, link, compile, link, 2 dyn. lib links + + EXPECT_TRUE(fs::exists("hello.o")); + EXPECT_TRUE(fs::exists("libhello.so.1.0.0")); + EXPECT_TRUE(fs::exists("libhello.so.1")); + EXPECT_TRUE(fs::exists("libhello.so")); + EXPECT_TRUE(fs::exists("runmain.o")); + EXPECT_TRUE(fs::exists("runmain")); + + result = run_command("./runmain", output); + EXPECT_EQ(result, 0); + ASSERT_EQ(output.size(), 1); + EXPECT_EQ(output[0], "Hello."); + + result = run_command("../ymake clean", output); + EXPECT_EQ(result, 0); + ASSERT_EQ(output.size(), 8); // hello.o, hello.d, hello.so.1.0.0, hello.so.1, hello.so, runmain.o, runmain.d, runmain + + EXPECT_TRUE(!fs::exists("hello.o")); + EXPECT_TRUE(!fs::exists("libhello.so.1.0.0")); + EXPECT_TRUE(!fs::exists("libhello.so.1")); + EXPECT_TRUE(!fs::exists("libhello.so")); + EXPECT_TRUE(!fs::exists("runmain.o")); + EXPECT_TRUE(!fs::exists("runmain")); +} + // TODO: -// use dynamic lib // use static lib from subdir // use dynamic lib from subdir // use static lib from subdir in subdir |