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

Nim language support #1756

Closed
Nuc1eoN opened this issue Oct 20, 2021 · 5 comments
Closed

Nim language support #1756

Nuc1eoN opened this issue Oct 20, 2021 · 5 comments

Comments

@Nuc1eoN
Copy link

Nuc1eoN commented Oct 20, 2021

Nim is a compiled language that is as fast and efficient as C but with a python-like syntax and many other features. It compiles to native C code (just like C++ in the old days) but lately also to javascript.

I would love to see Nim support in xmake and would certainly use it for my Nim projects :)

Nim has its own nimble package/project manager which could be compared to rust's cargo. I am not sure if in xmake we would implement support through nimble or bare nim compiler commands, or maybe both. But I guess the rust implementation could be a guideline.

@waruqi
Copy link
Member

waruqi commented Oct 21, 2021

I have supported it. #1759

Console

add_rules("mode.debug", "mode.release")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
$ xmake -v
[ 33%]: linking.release test
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache -o:b
uild/macosx/x86_64/release/test src/main.nim
[100%]: build ok!

Static Library

add_rules("mode.debug", "mode.release")

target("foo")
    set_kind("static")
    add_files("src/foo.nim")

target("test")
    set_kind("binary")
    add_deps("foo")
    add_files("src/main.nim")
$ xmake -v
[ 33%]: linking.release libfoo.a
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/foo/macosx/x86_64/release/nimcache --app
:staticlib --noMain --passC:-DNimMain=NimMain_B6D5BD02 --passC:-DNimMainInner=NimMainInner_B6D5B
D02 --passC:-DNimMainModule=NimMainModule_B6D5BD02 --passC:-DPreMain=PreMain_B6D5BD02 --passC:-D
PreMainInner=PreMainInner_B6D5BD02 -o:build/macosx/x86_64/release/libfoo.a src/foo.nim
[ 66%]: linking.release test
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache --pa
ssL:-Lbuild/macosx/x86_64/release --passL:-lfoo -o:build/macosx/x86_64/release/test src/main.nim
[100%]: build ok!

For static libraries, there is currently a _NimMain symbol redefinition bug that needs to be fixed. At present, I can only fix it temporarily through the workaround solution.

See nim-lang/Nim#15955

My workaround solution

function buildargv(self, sourcefiles, targetkind, targetfile, flags)
    local flags_extra = {}
    if targetkind == "static" then
        -- fix multiple definition of `NimMain', it is only workaround solution
        -- we need to wait for this problem to be resolved
        --
        -- @see https://github.com/nim-lang/Nim/issues/15955
        local uniquekey = hash.uuid(targetfile):split("-", {plain = true})[1]
        table.insert(flags_extra, "--passC:-DNimMain=NimMain_" .. uniquekey)
        table.insert(flags_extra, "--passC:-DNimMainInner=NimMainInner_" .. uniquekey)
        table.insert(flags_extra, "--passC:-DNimMainModule=NimMainModule_" .. uniquekey)
        table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey)
        table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey)
    end
    return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles)
end

Shared Library

add_rules("mode.debug", "mode.release")

target("foo")
    set_kind("shared")
    add_files("src/foo.nim")

target("test")
    set_kind("binary")
    add_deps("foo")
    add_files("src/main.nim")
$ xmake -rv
[ 33%]: linking.release libfoo.dylib
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/foo/macosx/x86_64/release/nimcache --app
:lib --noMain -o:build/macosx/x86_64/release/libfoo.dylib src/foo.nim
[ 66%]: linking.release test
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache --pa
ssL:-Lbuild/macosx/x86_64/release --passL:-lfoo -o:build/macosx/x86_64/release/test src/main.nim
[100%]: build ok!

With C Library

add_rules("mode.debug", "mode.release")

target("foo")
    set_kind("static")
    add_files("src/*.c")

target("test")
    set_kind("binary")
    add_deps("foo")
    add_files("src/main.nim")

Use packages

add_rules("mode.debug", "mode.release")

add_requires("zlib")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
    add_packages("zlib")

main.nim

proc zlibVersion(): cstring {.cdecl, importc}

echo zlibVersion()
$ xmake -v
[ 33%]: linking.release test
/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache --pas
sL:-L/Users/ruki/.xmake/packages/z/zlib/1.2.11/b76a297309d14c09b42cfe3927260a51/lib --passL:-lz -
o:build/macosx/x86_64/release/test src/main.nim
[100%]: build ok!
$ xmake r
1.2.11

@waruqi waruqi added this to the v2.5.9 milestone Oct 21, 2021
@waruqi
Copy link
Member

waruqi commented Oct 21, 2021

Some apis for nim

  • add_ncflags: for source file flags
  • add_ncldflags: for linker
  • add_ncarflags: for archive
  • add_ncshflags: for dynamic linker

@waruqi
Copy link
Member

waruqi commented Oct 21, 2021

I will improve the package management to directly install and integrate packages from nimble later, for example:

add_requires("nimble::zlib")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
    add_packages("nimble::zlib")

However, even if there is no nimble yet, we can use xmake's package management to directly integrate the c/c++ package from xmake-repo/vcpkg/conan in the nim project.

add_requires("zlib", "vcpkg::libpng")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
    add_packages("zlib", "vcpkg::libpng")

@waruqi
Copy link
Member

waruqi commented Oct 21, 2021

More Examples: https://github.com/xmake-io/xmake/tree/dev/tests/projects/nim

Project templates

xmake create -l nim -t console test
xmake create -l nim -t static test
xmake create -l nim -t shared test

@waruqi
Copy link
Member

waruqi commented Oct 27, 2021

We can use nimble packages now

Nimble packages

https://github.com/xmake-io/xmake/tree/dev/tests/projects/nim/nimble_package

add_rules("mode.debug", "mode.release")

add_requires("nimble::zip >0.3")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
    add_packages("nimble::zip")

main.nim

import zip/zlib

echo zlibVersion()

Native packages

https://github.com/xmake-io/xmake/tree/dev/tests/projects/nim/native_package

add_rules("mode.debug", "mode.release")

add_requires("zlib")

target("test")
    set_kind("binary")
    add_files("src/main.nim")
    add_packages("zlib")

main.nim

proc zlibVersion(): cstring {.cdecl, importc}

echo zlibVersion()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants