Skip to content

Allow tests to link against executable targets #3103

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

Conversation

abertelrud
Copy link
Contributor

@abertelrud abertelrud commented Dec 10, 2020

Experimental changes to allow test products to link against both Swift and Clang executable targets. This allows them to test everything except the main function in those targets without having to run the executable as a subprocess.

Motivation:

Many package authors don’t want to split their code into executable targets vs library targets, but still want to test data structures and algorithms in their executables.

Modifications:

This is experimental and not suitable for merging yet. It uses nmedit to elide the _main symbols from .o files from executables when a test product links them. This only works on Darwin; on Linux and Windows, the strip tool should usable but that hasn’t yet been tried.

There are several issues to address:

  • this isn’t particularly portable, since different implementations are required on different platforms; currently only Darwin is supported
  • it isn’t great from a performance perspective to have to create custom versions of the .o files from the executables
  • there isn’t any way for a unit test that depends on an executable to indicate whether it just wants a build-time dependency on the product or whether it wants to link against it
  • there’s something a bit conceptually shady about treating executables as libraries, so we will likely want to limit the types of targets that are allowed to link against executables to just unit tests
  • whatever tool is invoked on a particular platform should be found using the toolchain using a proper accessor
  • there are numerous FIXMEs in the code, especially related to the support for Clang executables
  • the test fixture isn’t yet being used

In the long run it would be better to have Swift and Clang changes to conditionally emit any _main symbol to a separate .o file that could be either included or excluded from a particular link command.

Result:

Unit tests that declare dependencies on executable targets will link against that code as well. We will need to consider the compatibility impacts of this, and might need to tie it to a tools version.

rdar://58122395

@abertelrud abertelrud requested a review from tomerd December 10, 2020 10:57
@abertelrud abertelrud marked this pull request as draft December 10, 2020 10:57
@abertelrud abertelrud self-assigned this Dec 10, 2020
@abertelrud abertelrud requested a review from compnerd December 10, 2020 11:04
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@compnerd
Copy link
Member

compnerd commented Dec 10, 2020

I think that we should possibly look at an older change of mine - marking main as hidden by default in the Swift compiler. In the case that the symbol is needed (because you are an executable) the C stub should cause it to be preserved via _start referencing main. That would obviate the need for the execution of nmedit and make this path identical across all the platforms.

BTW, strip is technically not available on Windows (although the current Swift toolchains being distributed do include it and thus would be there).

@abertelrud abertelrud changed the title Draft: Allow test products to link against executables WIP: Allow test products to link against executables Dec 10, 2020
@abertelrud
Copy link
Contributor Author

I think that we should possibly look at an older change of mine - marking main as hidden by default in the Swift compiler. In the case that the symbol is needed (because you are an executable) the C stub should cause it to be preserved via _start referencing main. That would obviate the need for the execution of nmedit and make this path identical across all the platforms.

Yes, doing this on the .o production side would definitely be better, though it wouldn't allow testing of Clang executables (not sure how important that is but it would be somewhat inconsistent). I'm not sure how feasible such a change would be, or how long that would take, but editing the symbol after-the-fact is definitely a stopgap.

BTW, strip is technically not available on Windows (although the current Swift toolchains being distributed do include it and thus would be there).

Right, that's what I actually meant to say (that it's currently available in the toolchain). I think on Linux as well, it comes from binutils which has to be installed via apt-get, etc.

@abertelrud abertelrud force-pushed the allow-test-products-to-link-against-executables branch from 9507ec2 to f25f609 Compare January 10, 2021 00:08

var tests = [XCTestCaseEntry]()
tests += TestableExeTests.allTests()
XCTMain(tests)
Copy link
Contributor

Choose a reason for hiding this comment

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

should not be required any longer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably not. I’ll try without it.

testCase(TestableExeTests.allTests),
]
}
#endif
Copy link
Contributor

@tomerd tomerd Jan 10, 2021

Choose a reason for hiding this comment

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

should not be required any longer?

@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud force-pushed the allow-test-products-to-link-against-executables branch from a6fd23c to 1f58ae7 Compare January 10, 2021 20:06
@abertelrud abertelrud marked this pull request as ready for review January 10, 2021 20:09
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud changed the title WIP: Allow test products to link against executables Allow tests to link against executable targets by creating alternate versions that elide the _main symbol Jan 10, 2021
@abertelrud abertelrud changed the title Allow tests to link against executable targets by creating alternate versions that elide the _main symbol Allow tests to link against executable targets Jan 10, 2021
…ort and test the code. Since compiler support isn't yet available, this implementation elides the `_main` symbol from the linked binary (using `nmedit` on Darwin and `objcopy` elsewhere). To produce alternate versions of .o files for the unit test to link against.
@abertelrud abertelrud force-pushed the allow-test-products-to-link-against-executables branch from 1f58ae7 to c8da0e3 Compare January 11, 2021 22:39
@tomerd tomerd marked this pull request as draft February 1, 2021 22:15
@abertelrud
Copy link
Contributor Author

Update: I will be reworking this to use the new Swift compiler flag in swiftlang/swift#35595.

@abertelrud
Copy link
Contributor Author

This is superseded by #3316 so I'm withdrawing this PR.

@abertelrud abertelrud closed this Mar 1, 2021
boraoku pushed a commit to boraoku/swiftmicrograd that referenced this pull request Sep 27, 2022
So removing all testing references. Reference for main statement: swiftlang/swift-package-manager#3103
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants