Questions:
- If the overview says slices can't be allocated with an allocator...
- Does odin have a code formatter, like gofmt?
- How I apply syntax highlighting to odin code in discord?
- Where's the documentation for Odin's 'prelude'?
- Why isn't it spelled os.CREAT like in POSIX?
- Will Odin ever add a C compiler?
- Why do I get a segfault on a Vulkan hello world?
- Why can't I link this ./shared.so library?!
- What's the difference between
#const n: intand$n: int?
... then how can slices be allocated?!
The overview says "Note: There is not automatic memory management in Odin. Slices may not be allocated using an allocator."
That doesn't mean 'may not' as a command, but as a possibility: slices can be backed by stack or static memory, not just dynamically allocated memory. This short program allocates the backing for a slice with the context allocator, assigns a slice of that memory to ns on the stack, prints the slice ([0, 0, 0, 0, 0]), and then leaves it to the OS to clean everything up:
package main
import "core:fmt"
main :: proc() {
ns := make([]int, 5)
fmt.println(ns)
}Does odin have a code formatter, like gofmt?
Yes. It's part of the Odin Language Server.
Building it for isolated use:
$ git clone https://github.com/DanielGavin/ols.git $ cd ols ols$ ./odinfmt.sh ols$ mv odinfmt ~/bin # or the like
Using it:
$ cat bad.odin
package main
import"core:fmt"
still_oneline::proc(){fmt.println( "hello world" )}
main::proc()
{
fmt.println("main")
}
$ odinfmt bad.odin
package main
import "core:fmt"
still_oneline :: proc() {fmt.println("hello world")}
main :: proc() {
fmt.println("main")
}
odinfmt's stricter than odin in some respects (requiring trailing commas where odin doesn't require them) and it doesn't do much with vertical whitespace or manage imports like 'goimports'. It does fix braces, nicely indents code, and it applies very readability-enhancing horizontal alignment. odinfmt has few CLI options but it can be configured with a JSON file.
NB. the core library doesn't use it (discord link)
How I apply syntax highlighting to odin code in discord?
Discord uses a vanilla https://highlightjs.org/ repo for its syntax highlighting, and they're not adding languages. So for the near term, you can't, and posting
```odin my odin code ```
will have monochromatic results. People occasionally post Odin code as if it were some other language to get some syntax highlighting, which is variously useful:
```go my odin code ```
Where's the documentation for Odin's 'prelude'?
https://github.com/odin-lang/Odin/blob/master/core/builtin/builtin.odin
Why isn't it spelled os.CREAT like in POSIX?
Ken Thompson wanted it that way
Will Odin ever add a C compiler?
Zig has zig cc, the entire llvm C compiler sharing its toolchain, and @cImport, directly parsing C code to import for use by Zig code. D also has ImportC, a new C compiler built out of dmd that can be used similarly, to compile C code that D can then import.
What about Odin? Discord link:
We do not plan on embedding the entirety of clang as part of the Odin toolchain.
zig cc is a better clang frontend which can deal with multiple C (and c stdlib) ABIs and comes with MUSL by default.
In many ways, it has little to do with Zig the language, but because Zig already uses LLVM, it can use its own zig cc to compile C code which it imports with @cImport.
If you are referring to the ability to import C code directly into a language, then we still do not plan to do this with Odin for a few reasons. We do have the foreign import system already which allows for interfacing with foreign languages such as C very easily, and it handles all of the linking for you too! This means you never have to specify linker flags directly pretty never again.
Odin won't ever have the ability to import C code directly for numerous reasons:
- A C compiler is a huge dependency, especially one which would be useful in practice with real world code.
- C is a broken language and it would require embedding a lot of the semantics of C into Odin. Zig for instance has the entire C type system embedded into its type system (for better or for worse) and takes advantage of all of the ABI handling it has to use for zig cc.
- C is actually TWO languages in one: the C preprocessor and the core C language. So it's a little more complex to deal with (especially with Odin's out of order declarations) than you might realize, and complex in the sense that it would be confusing as to when things would happen.
- When binding to a foreign library written in C, it is usually a lot better to use a binding generator (of which there are numerous community made ones for Odin) which will produce the Odin "headers" from the C code for you. This is because you pretty much only need to generate the header once and then you are done. You don't need to generate it every time you compile (even with caching). And with a generated interface, you can also modify the code too to better reflect what is actually happening without relying making a custom wrapper on top of it, something which is not possible with a language direct C importation.
Why do I get a segfault on a Vulkan hello world?
Apparently this is usually performed for you, hence it not showing up in typical vulkan docs, but you need to load some function pointers into some internal Vulkan state. Example from discord:
import win32 "core:sys/windows"
import vk "vendor:vulkan"
WString :: win32.utf8_to_wstring
VkLoader: win32.HMODULE
set_proc_address :: proc(p: rawptr, name: cstring) {
fptr := win32.GetProcAddress(VkLoader, name)
(cast(^rawptr)p)^ = fptr
}
init :: proc() {
VkLoader = win32.LoadLibraryW(WString("vulkan-1.dll"))
vk.load_proc_addresses(set_proc_address)
}Why can't I link this ./shared.so library?!
Depending on strange low-level linking decisions and the nature of the library at hand, a foreign import lib "./shared.so" which attempts to load a library in the current directory, it might result in a binary that doesn't appear to link against shared.so but looks for it at runtime:
$ odin build . $ ldd example.bin linux-vdso.so.1 (0x00007fff5631e000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f36eec81000) libm.so.6 => /usr/lib/libm.so.6 (0x00007f36eeb99000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f36eee9e000)
or it might result in a binary that tries to link against a "shared.so" which it can't find because this library isn't in the normal system search path:
$ odin build . $ ldd example.bin linux-vdso.so.1 (0x00007ffc097f7000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f9d51ee9000) libm.so.6 => /usr/lib/libm.so.6 (0x00007f9d51e01000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f9d52106000) shared.so => not found
You could resolve the latter case by changing ld's search path,
$ LD_LIBRARY_PATH=. ./example.bin
But another option is to embed the addition to the search path into the binary as you build it:
$ odin build . -extra-linker-flags:-Wl,-rpath=. $ ldd example.bin linux-vdso.so.1 (0x00007ffd689ab000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fb2af512000) libm.so.6 => /usr/lib/libm.so.6 (0x00007fb2af42a000) shared.so => ./shared.so (0x00007fb2af350000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fb2af72f000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fb2af34b000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fb2af114000) libasound.so.2 => /usr/lib/libasound.so.2 (0x00007fb2af023000) libmvec.so.1 => /usr/lib/libmvec.so.1 (0x00007fb2aef29000) libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fb2aef24000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fb2aef04000)
What's the difference between #const n: int and $n: int?
Consider these functions:
f1 :: proc(#const n: int) -> int { return n * 2 }
f2 :: proc($n: int) -> int { return n * 2 }Both functions require a constant parameter, but the first is a non-generic function that'll be given a static label like main.f1; the second is a generic function that might get instantiated multiple times (with cost: increased code size, and benefit: increased specialization).