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

[SR-1503] Can't test module under linux that has main.swift in it #5372

Open
swift-ci opened this issue May 12, 2016 · 6 comments
Open

[SR-1503] Can't test module under linux that has main.swift in it #5372

swift-ci opened this issue May 12, 2016 · 6 comments
Labels

Comments

@swift-ci
Copy link
Contributor

swift-ci commented May 12, 2016

Previous ID SR-1503
Radar rdar://problem/57595840
Original Reporter jaybuff (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 6
Component/s Package Manager
Labels Bug
Assignee None
Priority Medium

md5: b9c178bab17c28c88cc66850ac41c98e

is duplicated by:

  • SR-3033 Poor diagnostic when importing executable target module in a test
  • SR-4760 SwiftPM should support easier testing of CLI tools
  • SR-11866 SwiftPM: Test targets can't depend on executable products

Issue Description:

If I have a directory that has a source file and a main.swift in it (e.g. Sources/Foo/main.swift and Sources/Foo/Foo.swift) I can't write run a test for Foo.swift. I get an error that looks like this:

/code/.build/debug/Foo.build/main.swift.o: In function `main':
/code/Sources/Foo/main.swift:(.text+0x0): multiple definition of `main'
/tmp/LinuxMain-3d0090.o:/code/Tests/LinuxMain.swift:(.text+0x0): first defined here
@swift-ci
Copy link
Contributor Author

swift-ci commented May 13, 2016

Comment by Bhargav Gurlanka (JIRA)

I'm able to reproduce this issue. I think the main method generated in LinuxMain.swift file is causing the issue.

@aciidb0mb3r
Copy link
Member

aciidb0mb3r commented May 13, 2016

This is a known issue, executables are not yet testable.

@ddunbar
Copy link
Member

ddunbar commented Jun 7, 2016

This isn't something we can currently solve, at least in the way desired for here, where the Tests module is actually capable of importing the code in the executable module.

There are a couple reasons why this is difficult:

1. On Linux, where we need the tests to be a main executable (because of the XCTest implementation), then it isn't going to be possible to link together at all, because of the two main implementations. This is the immediate blocker.

2. Even if we didn't have a main executable, it isn't always possible to link for code which is compiled as the main executable. This is possible with Mach-O images, but I'm not sure if ELF does and I'm not 100% sure that Swift doesn't make assumptions about optimization of modules with main functions.

3. We could try and pull some switch where we built the executable but without its main.swift, but that would require duplicate compilation and break the Swift whole module compilation model (or at least, make it surprising).

The situation here is exactly like it is with C/C++ – if you want to be able to dynamically share/load a body of code it needs to be put into a library, not an executable.

I think what we should actually do for this specific code is not put the swift module for executables in a place it can be imported, but we can't otherwise support this without a radically different testing model which depends on the compilers ability to understand the test code (and compile it onto the side, or something).

@ddunbar
Copy link
Member

ddunbar commented Jun 7, 2016

I thought of one possible way we could do this...

We could allow the Package to declare its "entry points", and make executables just a kind of entry point, and let SwiftPM synthesize the code for the main executable. This would allow you to avoid ever writing the `main.swift` if it was as simple as a single function call. The upside of this approach is it also encourages people to write command line tools as testable libraries, which I think is a good thing. The downsides is it doesn't work with any other top-level code, which is very useful for small / script-style command line executables, so we would end up with two ways of doing things.

I'm not sure this is a good idea, but it is a feature I have seen before (Python's distutils can do this with its entry_points (http://python-packaging-user-guide.readthedocs.io/en/latest/distributing/#entry-points)).

@Lukasa
Copy link
Contributor

Lukasa commented Dec 3, 2019

I'm a bit concerned that we have left this open for three years without even proposing a documentation or error change to work around it. SwiftPM does actually know if a module has a `main.swift` in it, and we could surely arrange to get a somewhat helpful error message emitted that says "It looks like you're trying to test an executable: this isn't supported, consider moving the code you want to test into a library module instead." I've spoken to people who tried out Swift and bounced off because they hit this, which results in an ugly linker error.

While I'm here, I should note that the Package.swift that SwiftPM itself generates from swift package init --type=executable encourages you into this pattern, by having only a single executable target which is a dependency of the test target.

@Lukasa
Copy link
Contributor

Lukasa commented Dec 3, 2019

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants