From 9b6c531505ff74f119bff6facae35c10801b2c6c Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 31 May 2024 17:04:21 +0200 Subject: Link dynamic lib, test --- LanguageSettings.cpp | 7 ++++-- file.cpp | 16 ++++++++++++- file.h | 4 ++++ 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& 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(); } diff --git a/file.cpp b/file.cpp index b5cbe36..d4c3f54 100644 --- a/file.cpp +++ b/file.cpp @@ -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 paths {Reichwein::Stringhelper::split(env_value("PATH"), ":")}; diff --git a/file.h b/file.h index fbab148..972b580 100644 --- a/file.h +++ b/file.h @@ -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"( + + + libhello.so.1.0.0 + hello.cpp + + + runmain + runmain.cpp + libhello.so + + +)"); + + create_file("hello.cpp", R"(#include "hello.h" +#include +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 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 -- cgit v1.2.3