Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lld-macho] Find objects in library search path #78628

Merged
merged 7 commits into from
Jan 20, 2024
Merged

[lld-macho] Find objects in library search path #78628

merged 7 commits into from
Jan 20, 2024

Conversation

Un1q32
Copy link
Contributor

@Un1q32 Un1q32 commented Jan 18, 2024

Find object files in library search path just like Apple's linker, this makes building with some older MacOS SDKs easier since clang runs with -lcrt1.10.6.o

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 18, 2024

@llvm/pr-subscribers-lld

Author: None (OldWorldOrdr)

Changes

Find object files in library search path just like Apple's linker, this makes building with some older MacOS SDKs easier since clang runs with -lcrt1.10.6.o


Full diff: https://github.com/llvm/llvm-project/pull/78628.diff

1 Files Affected:

  • (modified) lld/MachO/Driver.cpp (+9-4)
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 401459a054394ec..f04165f5c026153 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -95,11 +95,16 @@ static std::optional<StringRef> findLibrary(StringRef name) {
               findPathCombination("lib" + name, config->librarySearchPaths,
                                   {".tbd", ".dylib", ".so"}))
         return path;
-      return findPathCombination("lib" + name, config->librarySearchPaths,
-                                 {".a"});
+      else if (std::optional<StringRef> path = findPathCombination(
+                   "lib" + name, config->librarySearchPaths, {".a"}))
+        return path;
+      return findPathCombination(name, config->librarySearchPaths, {""});
     }
-    return findPathCombination("lib" + name, config->librarySearchPaths,
-                               {".tbd", ".dylib", ".so", ".a"});
+    if (std::optional<StringRef> path =
+            findPathCombination("lib" + name, config->librarySearchPaths,
+                                {".tbd", ".dylib", ".so", ".a"}))
+      return path;
+    return findPathCombination(name, config->librarySearchPaths, {""});
   };
 
   std::optional<StringRef> path = doFind();

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 18, 2024

@llvm/pr-subscribers-lld-macho

Author: None (OldWorldOrdr)

Changes

Find object files in library search path just like Apple's linker, this makes building with some older MacOS SDKs easier since clang runs with -lcrt1.10.6.o


Full diff: https://github.com/llvm/llvm-project/pull/78628.diff

1 Files Affected:

  • (modified) lld/MachO/Driver.cpp (+9-4)
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 401459a054394e..f04165f5c02615 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -95,11 +95,16 @@ static std::optional<StringRef> findLibrary(StringRef name) {
               findPathCombination("lib" + name, config->librarySearchPaths,
                                   {".tbd", ".dylib", ".so"}))
         return path;
-      return findPathCombination("lib" + name, config->librarySearchPaths,
-                                 {".a"});
+      else if (std::optional<StringRef> path = findPathCombination(
+                   "lib" + name, config->librarySearchPaths, {".a"}))
+        return path;
+      return findPathCombination(name, config->librarySearchPaths, {""});
     }
-    return findPathCombination("lib" + name, config->librarySearchPaths,
-                               {".tbd", ".dylib", ".so", ".a"});
+    if (std::optional<StringRef> path =
+            findPathCombination("lib" + name, config->librarySearchPaths,
+                                {".tbd", ".dylib", ".so", ".a"}))
+      return path;
+    return findPathCombination(name, config->librarySearchPaths, {""});
   };
 
   std::optional<StringRef> path = doFind();

Copy link
Collaborator

@smeenai smeenai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks :)

This needs a test case. You'll find lots of existing test cases under lld/test/MachO which should be good templates for this (and there's likely an existing test case you can extend to cover your new logic).

else if (std::optional<StringRef> path = findPathCombination(
"lib" + name, config->librarySearchPaths, {".a"}))
return path;
return findPathCombination(name, config->librarySearchPaths, {""});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this needs to be two separate calls to findPathCombination, instead of keeping one call and making the argument {".a", ""})? IIUC, the difference will be in a scenario where your search path has /foo and /bar, the files /foo/crt1.o and /bar/crt1.o.a exist, and you do -lcrt1.o. Your current logic will find /bar/crt1.o.a, whereas a single call would find /foo/crt1.o. What does ld64 do? If you do need the separate calls to match ld64's behavior then it's worth adding a comment to explain that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you suggesting the code be

      return findPathCombination("lib" + name, config->librarySearchPaths,
                                 {".a", ""});

Won't that look for libcrt1.o instead of crt1.o?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right; that was a think-o on my part :) That being said, the scenario in my first comment (except with /bar/libcrt1.o.a) still applies; it's an edge case, but if we're matching ld64 behavior, we might as well match it as closely as reasonable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a quick test with both libcrt1.o.a and crt1.o shows ld64 prefers crt1.o

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. In that case, we probably want to instead change findPathCombination to take a list of prefixes, so that we can match ld64's search behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing the object and trying again gives an error, ld64 wont link with the .a file at all

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, that's interesting. I wonder if they have some special-cased logic around these specific extensions, or if they just won't append the .a if there's already any other extension present...

Copy link
Contributor Author

@Un1q32 Un1q32 Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like ld64 checks if the library name ends in .o and if so, assumes it's a Csu support file, and looks for a file in the library search path with that exact name, not searching for any libcrt1.o.a.

If a Csu support file is not found ld64 automatically changes the target to MacOS 10.8 which stopped requiring Csu support files, then continues.

Apples new linker does the same, but it has no concept of Csu support files and just links with it like it were a normal file, exiting with an error if it's not found.

@Un1q32
Copy link
Contributor Author

Un1q32 commented Jan 19, 2024

Patch reworked to more closely replicate ld64's behavior.

@smeenai
Copy link
Collaborator

smeenai commented Jan 19, 2024

Thanks, the code looks good to me. Could you add a short comment explaining why we're special casing the .o extension, and also add a test case?

@Un1q32
Copy link
Contributor Author

Un1q32 commented Jan 19, 2024

I've added a basic comment and a test case, I've never written a test with lit before so sorry if its terrible and broken

# RUN: mkdir -p %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/libhello.s -o %t/hello.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/main.o
# RUN: %lld -L %t %t/main.o %t/hello.o -o %t/a.out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be some basic verification of the output after the link?

@@ -90,6 +90,9 @@ static std::optional<StringRef> findLibrary(StringRef name) {
return entry->second;

auto doFind = [&] {
// Special case for Csu support files.
Copy link
Member

@oontvoo oontvoo Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would be helpful to expand what Csu files are ... (not a very common thing - I had to look it up :) )

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the new comment ok?

Copy link

github-actions bot commented Jan 19, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@Un1q32
Copy link
Contributor Author

Un1q32 commented Jan 19, 2024

Updated the test to verify the output

Copy link
Member

@oontvoo oontvoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@thevinster
Copy link
Contributor

thevinster commented Jan 20, 2024

Do you have write permissions? Or, were you waiting for someone to help you merge this PR?

@Un1q32
Copy link
Contributor Author

Un1q32 commented Jan 20, 2024

I'm just some guy I don't have write perms, this is my first time contributing to llvm

@thevinster thevinster merged commit 46a9135 into llvm:main Jan 20, 2024
3 of 4 checks passed
# RUN: mkdir -p %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/libhello.s -o %t/hello.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/main.o
# RUN: %lld -L %t %t/main.o %t/hello.o -o %t/a.out
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should one of these be linked with -l instead of by path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AHH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed it in my branch but the pr is already merged

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you mind putting it in another PR? we can get it merged there. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you mind putting it in another PR? we can get it merged there. Thanks!

done #79018

@Un1q32 Un1q32 mentioned this pull request Jan 22, 2024
oontvoo pushed a commit that referenced this pull request Jan 23, 2024
Mistake with #78628 that got caught after being merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants