summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2024-05-31 17:04:21 +0200
committerRoland Reichwein <mail@reichwein.it>2024-05-31 17:04:21 +0200
commit9b6c531505ff74f119bff6facae35c10801b2c6c (patch)
treee8efa038553588a7f4bde3f3ebe2cc3c996baf73
parent92be2196d6515f854295b0b830ad7dd4b97bb956 (diff)
Link dynamic lib, test
-rw-r--r--LanguageSettings.cpp7
-rw-r--r--file.cpp16
-rw-r--r--file.h4
-rw-r--r--test-ymake.cpp65
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();
}
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<std::string> 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"(
+<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