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-12683] @main is no longer usable due to misdetection of top level code #55127

Open
compnerd opened this issue Apr 27, 2020 · 6 comments
Open

[SR-12683] @main is no longer usable due to misdetection of top level code #55127

compnerd opened this issue Apr 27, 2020 · 6 comments
Labels

Comments

@compnerd
Copy link
Collaborator

@compnerd compnerd commented Apr 27, 2020

Previous ID SR-12683
Radar rdar://problem/62475602
Original Reporter @compnerd
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 16
Component/s
Labels Bug
Assignee None
Priority Medium

md5: d99a1a03d2003d32b1bfd6a2ae65a2fa

is duplicated by:

Issue Description:

There seems to be a recent regression with comment blocks and functions being treated as top level code which prevents the use of `@main`.

@natecook1000
Copy link
Member

@natecook1000 natecook1000 commented Apr 28, 2020

@swift-ci create

@natecook1000
Copy link
Member

@natecook1000 natecook1000 commented Apr 28, 2020

It looks like compilation is failing whenever the compiler's in single-file mode. Using the two attached source files, I get this result from trying to compile just MyMain.swift:

$ swiftc MyMain.swift
MyMain.swift:3:1: error: 'main' attribute cannot be used in a module that contains top-level code
@main
^
MyMain.swift:1:1: note: top-level code defined in this source file
// @main attribute test
^

When I add Empty.swift, the issue goes away:

$ swiftc MyMain.swift Empty.swift
(compiles without issue)

@natecook1000
Copy link
Member

@natecook1000 natecook1000 commented Apr 28, 2020

To make this work, you can tell the compiler to parse the file as a library instead of in single-file mode with the -parse-as-library flag:

$ swiftc -parse-as-library MyMain.swift

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Aug 6, 2021

Comment by Josh Wright (JIRA)

Any updates to this? Hitting this issue as well when writing a single file script.

Nate's workaround works, but would be great to have this work out of the box (was using it indirectly through https://github.com/mxcl/swift-sh so it wasn't apparent how to update the compiler flags).

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Sep 18, 2021

Comment by Eneko Alonso (JIRA)

This seems to still be an issue for new Swift 5.5 packages containing a main.swift file.

Steps to reproduce:

  1. mkdir myapp && cd myapp
  2. swift package init --type executable
  3. Replace `main.swift` content with the following

{{
@main
struct Program {
static func main() {
print("Hello, world!")
}
}
}}

4. swift run
5. Observe error: main.swift:2:1: error: 'main' attribute cannot be used in a module that contains top-level code

Multiple files

Adding a second file does not seem to fix the issue:

  1. create a second file Hello.swift with this content

{{
func hello() {
print("Hello, world!")
}
}}

2. Update `main.swift` as follows:

{{
@main
struct Program {
static func main() {
hello()
}
}
}}

3. swift run
4. Observe error: main.swift:2:1: error: 'main' attribute cannot be used in a module that contains top-level code

Solution

Renaming `main.swift` to something else (eg. `Program.swift`) solves the issue, whether there are only one file or more.

  1. Delete Hello.swift
  2. Update main.swift as follows:

{{
func hello() {
print("Hello, world!")
}

@main
struct Program {
static func main() {
hello()
}
}
}}

3. swift run
4. Observer the output "Hello, world!"

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@ubunatic
Copy link

@ubunatic ubunatic commented Apr 29, 2022

I can confirm the issue for this example where I import a cooperating module:

// Swift version 5.6 (swift-5.6-RELEASE)
// Target: arm64-apple-macosx12.0
import Foundation
import SwiftUI
import HelloCore

@main
struct HelloApp: App {
    var body: some Scene {
        WindowGroup {
            HelloView().onAppear {
                print("loaded")
                signal(SIGINT) { _ in
                    print("exit")
                    exit(EXIT_SUCCESS)
                }
            }
        }
    }
}

The renaming solution works. However, you may then see swift build errors such as:

'Hello': error: executable product 'Hello' expects target 'Hello' to be executable;
an executable target requires a 'main.swift' file

You can fix that by changing the .target in your Package.swift to .executableTarget.

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

4 participants