# How to actually make a main function

**URL:** https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881
**Category:** General Usage
**Created:** [June 14, 2025, 3:40pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881 "2025-06-14T15:40:37Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![The\_Mastermage](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/the_mastermage/32/49444_2.png) [@The\_Mastermage](https://discourse.julialang.org/u/The_Mastermage)
#### Post date: [June 14, 2025, 3:40pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/1 "2025-06-14T15:40:37Z")

</div>

Whilst trying to write a small HTTP server just for fun. I was trying to figure out how to use an actual main function. I am most of the time usualy just scripting, so I havent realy used the new @main syntax yet.

The following is my code:

```julia
module http_server_julia

using Sockets
using Logging

struct TCPServer
    host::String
    port::Int
end

TCPServer() = TCPServer("127.0.0.1",8888)

#= function start(server::TCPServer)

    tcp_server = Sockets.listen(server.host, server.port)
    
    while True
    
        connection = Sockets.accept(tcp_server)
        @info "Connected by"  
    end
end =#

export main
(@main)(args) = println("Hello from the package!")

end # module http_server_julia

```

Ignore the fact that I havent figured out how to use the socket library yet. But no matter what i do, even just straigth up copying this from the main docs, I cannot get even a simple print to run. It just flat out does not work. I am loosing my mind right now. It can’t be that dificult to use the main function.

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [June 14, 2025, 3:56pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/2 "2025-06-14T15:56:20Z")

</div>

Have you tried adding

```julia
using .http_server_julia

```

at the very end of your file?

---

<div class="post-metadata">

### Author: ![The\_Mastermage](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/the_mastermage/32/49444_2.png) [@The\_Mastermage](https://discourse.julialang.org/u/The_Mastermage)
#### Post date: [June 14, 2025, 4:05pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/3 "2025-06-14T16:05:18Z")

</div>

ok yes that makes it work but why, and excuse my language here in all flying hells does this now work. Why is this required? WTF?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [June 14, 2025, 5:22pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/4 "2025-06-14T17:22:12Z")

</div>

this would have also worked if you removed the `module`. the reason is that `@main` needs to be at the top level, since program entrypoint is a global, not a local property. `using` the middle brings the main function into the global scope

---

<div class="post-metadata">

### Author: ![eteppo](https://avatars.discourse-cdn.com/v4/letter/e/90db22/32.png) [@eteppo](https://discourse.julialang.org/u/eteppo)
#### Post date: [June 14, 2025, 6:07pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/5 "2025-06-14T18:07:42Z")

</div>

In other words the command-line Julia runs `Main.main(ARGS)` automatically if you use `@main` to opt-in to it. So you need to define this function either inside the `Main` module directly or bring it into `Main` from another module `using .MyModule` or other. [Command-line Interface · The Julia Language](https://docs.julialang.org/en/v1/manual/command-line-interface/#The-Main.main-entry-point)

---

<div class="post-metadata">

### Author: ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)
#### Post date: [June 14, 2025, 6:12pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/6 "2025-06-14T18:12:25Z")

</div>

I never bother with main. I just put the stuff into a “top” function and I call it at the bottom of the script.

---

<div class="post-metadata">

### Author: ![The\_Mastermage](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/the_mastermage/32/49444_2.png) [@The\_Mastermage](https://discourse.julialang.org/u/The_Mastermage)
#### Post date: [June 15, 2025, 7:32am UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/7 "2025-06-15T07:32:30Z")

</div>

Ah that makes sense to me now. Does that also work in the case of having multiple files in a package? Or how does one show the Julia Compiler which file has the entry point?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [June 15, 2025, 11:01pm UTC](https://discourse.julialang.org/t/how-to-actually-make-a-main-function/129881/8 "2025-06-15T23:01:02Z")

</div>

Let’s look at what an entry point or main function is. In the most straightforward definition, this is where your program starts execution after loading the necessary code. In many approaches, you denote the start (and end) of the program in a function with a specific signature and name, often “main” or something similar. Your program can’t start in several places at once, so there’s an ahead-of-time (AOT) compiler that looks at all of your code and complains if it finds multiple main functions. This does apply if you were compiling PackageCompiler.jl apps (`julia_main()::Cint`) or the upcoming juliac executables (`Base.@ccallable main()::Cint`, the last time I read about it).

When you run the `julia` command, you’re not AOT-compiling the input code, regardless of whether you’re entering an interactive REPL session or going back to the command line afterward. With the exception of what packages installed in a given environment opted to precompile, Julia parses and executes expressions one by one and compiles native code just-in-time (JIT), on demand. Your program started at the first line and ended at the last line like any of your scripts; the last thing it did was define a `(@main)(args)` method you never call and wrap up the module. (Technically `(@main)` expands to the simple function name `main`, but the macro call also does a critical registration step in the background, so I’ll keep referring to the definition by the macro call). If you just needed to run a program from the command line, you didn’t need the enclosing module, you didn’t need a `(@main)` function, and you didn’t need to wrap your primary work in one function to call (though it’s much easier for the JIT compiler to optimize a function call, so it’s often recommended).

So if `(@main)` isn’t where the Julia program begins, what is it? Its docstring refers to it as _an_ entry point for the _current module_, not one for the whole program. The command line interface documentation documents the `-m`/`--module` flag as running the `(@main)` entry point for a package (all packages are modules hence the flag’s name). Each module can have its own `(@main)` to implement an application routine of sorts in addition to the usual library routines, and it can run automatically from the command line with the `-m`/`--module` flag or with a unique import of `main` to the `Main` module that all Julia programs start in (which is what the `-m` flag does for packages). `Main.main(ARGS)` executes when the process is about to automatically `exit`, so this arguably isn’t an “entry point” at all, but that’s the term we have to live with.

This is and likely will remain a very rarely used feature because it saves negligible effort compared to any explicit function call, including `hppt_server_julia.main(ARGS)`. The only way to entirely avoid an explicit function call or import statement in `Main` is the `-m` flag or defining `(@main)` right in `Main` of the input file or expression at the command line, and that import statement can otherwise become about as long because packages on principle won’t export a common or conventional name like `main` via bare `using` statements. It is really only convenient for the `-m` flag, but I’ve never ran across a package to use it for and it doesn’t even seem available for me (v1.11.5, Windows).

> [@The\_Mastermage](#):
>
> Why is this required? WTF?

You might be going back to this question at this point because your script only has the one `(@main)`, so shouldn’t Julia be able to automatically identify this and run it for you, even if the program doesn’t really start there? At least 2 problems: 1) Julia doesn’t have an AOT compiler by default to even try to identify and enforce one `(@main)` definition, and 2) multiple coexisting modules allow multiple `(@main)` by design. If you import a package with a `(@main)` before your own, then `include` another module file with a `(@main)`, there’s no good reason to automatically call your `(@main)` instead of the others. A definition or import into `Main` is crucial for stable selection.
