Hi,
As a learning exercise I am implementing some algorithms from Knuth's volume 4B in Nim. Specifically, I am working through his chapter on the "dancing links" algorithm for exact cover problems.
There are several variants of this algorithm and they have slightly different underlying datatypes. I would like to be able to import a common datatypes module into various algorithm implementation modules and have the imported datatypes (and some other support code) vary as needed. That is, something like this:
# In module D, the datatypes:
when defined(it_is_for_algo_1):
type
# ...
elif defined(it_is_for_algo_2):
type
# ...
# etc..
# In module A1
const it_is_for_algo_1* = 1
import D
# In module A2
const it_is_for_algo_2* = 1
import D
I have tried this but module D doesn't see the it_is_for_algo_X consts, presumably because D doesn't import A1 and A2.
Is there a way to make this happen? I guess I could include instead of import, but I have some data hiding in the D module that I'd prefer to keep.
Alternatively I could handle this at build time since algo 1 and algo 2 will be separate binaries. I could manually put "-d:it_is_for_algo{1,2}" on the command line when building them but want to avoid this. I am using "nimble build" to build. Can I specify binary-specific defines for the nimble build process? I'd prefer not to have to go back to using make.
const is_it_for_algo_N {.intdefine.} = 1
when is_it_for_algo_N == 1:
import A
elif is_it_for_algo_N == 2:
import B
And pass nim c -d:is_it_for_algo_N=2 yourfile.nim
Or just put the alternate type definition instead of the imports.
Can I specify binary-specific defines for the nimble build process?
You can specify which kind of binary built with nimble task. See here
You can also make a config file specific to your nim file so the name is yourfile.nim.cfg and put the options in it like
-d:it_is_for_algo{1,2}
So whenever nim c yourfile.nim is invoked, it automatically add options specified in your config file.
Thanks for both of your replies.
mratsim: I don't think that approach will give me quite what I want as my import dependencies go the other way. Rather than defining the flag in a file and deciding which file to import from there, I need to import a particular file from each of two places and have it do slightly different things in each case.
mashingan: That is what I need. The yourfile.nim.cfg file is exactly what I need to define this for the compiler.
Thanks again!
So the alternative I mentioned doesn't work either?
const is_it_for_algo_N {.intdefine.} = 1
when is_it_for_algo_N == 1:
type Foo = object
val: int
elif is_it_for_algo_N == 2:
type Foo = object
val: string
That works fine when I set the const from the command line when building:
$ nim c -r -d:is_it_for_algo_N=1 algo_1
$ nim c -r -d:is_it_for_algo_N=2 algo_2
But it isn't enough to "set" the const in the algo-specific source file:
# In algo_<X>.nim
const is_it_for_algo_N {.intdefine.} = 1
import algo_common
where your sample code is in algo_common.nim.
I had hoped to keep this sort of config/compile-time setup in the .nim source files so there is only one place to look, but supplying the correct value at build time via the algo_<X>.nim.cfg is not a hardship.
(BTW: how can I insert a decorated username in my forum replies when responding?)