www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - D packages, include directories, and rdmd

reply Andrew Pennebaker <andrew.pennebaker gmail.com> writes:
I've got a single-file D module,
dashcheck.d<https://github.com/mcandre/dashcheck>,
that I'd like to install as a local package. In other words, I'd like to be
able to "import dashcheck;" from any directory.

I put dashcheck.d in ~/.d/, and I put export DFLAGS=-I~/.d in ~/.profile,
but when I try to run example.d from another directory, I get:

$ ./example.d
./example.d(3): Error: module dashcheck is in file 'dashcheck.d' which
cannot be read
import path[0] = /usr/local/Cellar/dmd/2.051/src/phobos
import path[1] = /usr/local/Cellar/dmd/2.051/src/druntime/importCheers,

It appears that rdmd ignores $DFLAGS.

Also, when I change the shebang in example.d to #!/usr/bin/env rdmd $DFLAGS,
I get:

$ ./example.d
sh: -I~/.d.d.deps: No such file or directory

So I'm not using import directives correctly. How do I generate
dashcheck.d.deps?

Andrew Pennebaker
www.yellosoft.us
Oct 27 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrew Pennebaker" <andrew.pennebaker gmail.com> wrote in message 
news:mailman.543.1319752640.24802.digitalmars-d puremagic.com...
 I've got a single-file D module,
 dashcheck.d<https://github.com/mcandre/dashcheck>,
 that I'd like to install as a local package. In other words, I'd like to 
 be
 able to "import dashcheck;" from any directory.

 I put dashcheck.d in ~/.d/, and I put export DFLAGS=-I~/.d in ~/.profile,
 but when I try to run example.d from another directory, I get:

 $ ./example.d
 ./example.d(3): Error: module dashcheck is in file 'dashcheck.d' which
 cannot be read
 import path[0] = /usr/local/Cellar/dmd/2.051/src/phobos
 import path[1] = /usr/local/Cellar/dmd/2.051/src/druntime/importCheers,

 It appears that rdmd ignores $DFLAGS.
I guess DFLAGS isn't an env var (which actually surprises me, it probably should be, is there already an enhancement request in bugzilla for that? Is is there some deliberate reason for this?). DFLAGS is normally set in your dmd.conf file (sc.ini on Windows). Do a "which dmd" to see where your dmd binary is, and your dmd.conf will be in the same directory (at least if you used the .zip releases or DVM, I don't know where the distros will put dmd.conf). Another approach that many of us use is to just pass the -Ipath option to dmd or rdmd in your buildscript to tell dmd/rdmd where to look for look for imports (sort of the D counterpart to Java's classpaths).
 Also, when I change the shebang in example.d to #!/usr/bin/env rdmd 
 $DFLAGS,
 I get:

 $ ./example.d
 sh: -I~/.d.d.deps: No such file or directory

 So I'm not using import directives correctly. How do I generate
 dashcheck.d.deps?
Part of the problem here is the same as above, DFLAGS needs to be set in dmd.conf, not an env var. But also, when you use rdmd as a shebang, you should use the --shebang option (always as the first argument), ie: #!/usr/bin/env rdmd --shebang {whatever other options here} Apperently, shebangs tend to mess up the params that get sent to rdmd, and the --shebang makes it use an alternate approach made specifically for that situation.
Oct 27 2011
parent reply Andrew Pennebaker <andrew.pennebaker gmail.com> writes:
In addition, I can't even use a naked -I directive without all the
dmd.conf/DFLAGS stuff.

My module code is in ~/Desktop/src/dashcheck. But even with the -Ipath
directive, dmd still can't find it.

$ dmd example.d -I~/Desktop/src/dashcheck
Undefined symbols for architecture i386:
  "_D9dashcheck12__ModuleInfoZ", referenced from:
      _D7example12__ModuleInfoZ in example.o
  "_D9dashcheck9genStringFZAya", referenced from:
      anon in example.o
  "_D9dashcheck6genIntFZi", referenced from:
      anon in example.o
      _D7example7genEvenFZi in example.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
--- errorlevel 1

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Thu, Oct 27, 2011 at 6:28 PM, Nick Sabalausky <a a.a> wrote:

 "Andrew Pennebaker" <andrew.pennebaker gmail.com> wrote in message
 news:mailman.543.1319752640.24802.digitalmars-d puremagic.com...
 I've got a single-file D module,
 dashcheck.d<https://github.com/mcandre/dashcheck>,
 that I'd like to install as a local package. In other words, I'd like to
 be
 able to "import dashcheck;" from any directory.

 I put dashcheck.d in ~/.d/, and I put export DFLAGS=-I~/.d in ~/.profile,
 but when I try to run example.d from another directory, I get:

 $ ./example.d
 ./example.d(3): Error: module dashcheck is in file 'dashcheck.d' which
 cannot be read
 import path[0] = /usr/local/Cellar/dmd/2.051/src/phobos
 import path[1] = /usr/local/Cellar/dmd/2.051/src/druntime/importCheers,

 It appears that rdmd ignores $DFLAGS.
I guess DFLAGS isn't an env var (which actually surprises me, it probably should be, is there already an enhancement request in bugzilla for that? Is is there some deliberate reason for this?). DFLAGS is normally set in your dmd.conf file (sc.ini on Windows). Do a "which dmd" to see where your dmd binary is, and your dmd.conf will be in the same directory (at least if you used the .zip releases or DVM, I don't know where the distros will put dmd.conf). Another approach that many of us use is to just pass the -Ipath option to dmd or rdmd in your buildscript to tell dmd/rdmd where to look for look for imports (sort of the D counterpart to Java's classpaths).
 Also, when I change the shebang in example.d to #!/usr/bin/env rdmd
 $DFLAGS,
 I get:

 $ ./example.d
 sh: -I~/.d.d.deps: No such file or directory

 So I'm not using import directives correctly. How do I generate
 dashcheck.d.deps?
Part of the problem here is the same as above, DFLAGS needs to be set in dmd.conf, not an env var. But also, when you use rdmd as a shebang, you should use the --shebang option (always as the first argument), ie: #!/usr/bin/env rdmd --shebang {whatever other options here} Apperently, shebangs tend to mess up the params that get sent to rdmd, and the --shebang makes it use an alternate approach made specifically for that situation.
Oct 27 2011
parent "Nick Sabalausky" <a a.a> writes:
"Andrew Pennebaker" <andrew.pennebaker gmail.com> wrote in message 
news:mailman.545.1319755391.24802.digitalmars-d puremagic.com...
 In addition, I can't even use a naked -I directive without all the
 dmd.conf/DFLAGS stuff.

 My module code is in ~/Desktop/src/dashcheck. But even with the -Ipath
 directive, dmd still can't find it.

 $ dmd example.d -I~/Desktop/src/dashcheck
 Undefined symbols for architecture i386:
  "_D9dashcheck12__ModuleInfoZ", referenced from:
      _D7example12__ModuleInfoZ in example.o
  "_D9dashcheck9genStringFZAya", referenced from:
      anon in example.o
  "_D9dashcheck6genIntFZi", referenced from:
      anon in example.o
      _D7example7genEvenFZi in example.o
 ld: symbol(s) not found for architecture i386
 collect2: ld returned 1 exit status
 --- errorlevel 1
DMD found it as an import, you're just getting linker errors because you didn't tell DMD to actually compile dashcheck.d as well. For better or worse, DMD only compiles the files you give it, just like any old C/C++ compiler: dmd example.d ~/Desktop/src/dashcheckdashcheck.d -I~/Desktop/src/dashcheck RDMD, on the other hand, will actually go ahead and compile all the necessary .d files: rdmd --buildonly -I~/Desktop/src/dashcheck example.d (Note that RDMD requires the .d file to be the last parameter. Run rdmd with no args for more details.) There's one more thing though: I noticed from your OP that you're using DMD 2.051. The RDMD included in that is riddled with fairly major bugs that have all since been fixed. You're going to have a hard time getting that old RDMD to work right. So you should grab the rdmd binary from the latest release (2.056): http://ftp.digitalmars.com/dmd.2.056.zip You can just replace your existing rdmd binary with the one in there. It should still work with DMD 2.051. Of course, DMD 2.051 itself is getting a bit old too, so you may want to think about just simply upgrading to 2.056.
Oct 27 2011
prev sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Andrew Pennebaker Wrote:

 I've got a single-file D module,
 dashcheck.d<https://github.com/mcandre/dashcheck>,
 that I'd like to install as a local package. In other words, I'd like to be
 able to "import dashcheck;" from any directory.
 
 I put dashcheck.d in ~/.d/, and I put export DFLAGS=-I~/.d in ~/.profile,
 but when I try to run example.d from another directory, I get:
Just a theory but I suspect that DFLAGS in dmd.conf just override the environment you specify. You should be able to specify -I yourself but ~ may not be resolved. Also you must have a library and specify the library path -L-L or place it in a known location like /usr/local/lib
Oct 27 2011
parent reply Andrew Pennebaker <andrew.pennebaker gmail.com> writes:
Nick, thanks for the info. I'm upgrading my Homebrew D installation now.
What's the point of -Ipath for dmd if you still have to specify the actual
files in the path?

I'm not sure if this is the right mailing list, but I'd really like to see
rdmd using the $DFLAGS environment variable like dmd does. For now, I'll use
your handy shebang tip.

Can future versions of rdmd turn on --shebang by default? I can't think of a
reason to give coders the ability to not support shebang options.

Jesse, aye, DFLAGS in dmd.conf appears to override the default rather than
append to the default. And that's just silly.

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Thu, Oct 27, 2011 at 7:17 PM, Jesse Phillips
<jessekphillips+D gmail.com>wrote:

 Andrew Pennebaker Wrote:

 I've got a single-file D module,
 dashcheck.d<https://github.com/mcandre/dashcheck>,
 that I'd like to install as a local package. In other words, I'd like to
be
 able to "import dashcheck;" from any directory.

 I put dashcheck.d in ~/.d/, and I put export DFLAGS=-I~/.d in ~/.profile,
 but when I try to run example.d from another directory, I get:
Just a theory but I suspect that DFLAGS in dmd.conf just override the environment you specify. You should be able to specify -I yourself but ~ may not be resolved. Also you must have a library and specify the library path -L-L or place it in a known location like /usr/local/lib
Oct 27 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrew Pennebaker" <andrew.pennebaker gmail.com> wrote in message 
news:mailman.550.1319767813.24802.digitalmars-d puremagic.com...
 Nick, thanks for the info. I'm upgrading my Homebrew D installation now.
 What's the point of -Ipath for dmd if you still have to specify the actual
 files in the path?
It has to do with D's C/C++ legacy, and the traditional C/C++ build model. In C/C++, you can compile difference sources separately, and *then* link them together - in fact, that's the old traditional way to do it: (I might not have these commands correct, I don't use gcc much) $ gcc -c -I~/ -I~/zlib a.c # compile to a.o, imports/headers can be found in ~/ and ~/zlib $ gcc -c ~/b.c # compile to b.o $ gcc -c ~/c.c # compile to c.o $ ld -of app a.o b.o c.o ~/zlib/zlib.lib # link together into app, along with pre-built zlib $ ./app # run app D retains that ability: $ dmd -c -I~/ -I~/zlib a.d # compile to a.o, imports/headers can be found in ~/ and ~/zlib $ dmd -c ~/b.d # compile to b.o $ dmd -c ~/c.d # compile to c.o $ dmd -ofapp a.o b.o c.o ~/zlib/zlib.lib # link together into app, along with pre-built zlib $ ./app # run app And as a shortcut, modern C/C++ and D compilers offer the ability to simplify that all into one command: $ dmd -ofapp -I~/zlib a.d ~/b.d ~/c.d ~/zlib/zlib.lib # shortcut for the above statements But the old way is still possible becuause sometimes it can be useful (for instance, if a b and c are all in different languages, or if you want them each compiled with different settings, or to speed up long C/C++ compile times by compiling different parts on different machines). So that leads to this: Regardless of whether you do that in C/C++ or D: Suppose 'a' imports 'b', and inside 'a' you call a function from 'b'. If you've told it to *only* compile 'a' and not 'b' (because you intend to do it all separately) how does the compiler know that function you're using actually exists if you've only given it 'a'? Or if 'a' uses a class defined in 'b', how does the compiler know what members the class has if you only told it to compile 'a'? It has to find 'b', open it, and check. That's what -Ipath is for, so it knows where to find 'b' so it can find out what's in 'b', so that it can compile 'a' regardless of whether or not it's actually compiling 'b' as well. Of course, in most cases with D, all of that "one at a time" junk is just a pointless PITA, so fortunately we have RDMD to find all the .d files and just shove them all off to be compiled. So this: $ dmd -ofapp -I~/zlib a.d ~/b.d ~/c.d ~/zlib/zlib.lib Becomes this: $ rdmd --build-only -ofapp -I~/zlib ~/zlib/zlib.lib a.d Note that ~/b.d and ~/c.d were omitted because RDMD will just find them itself, thanks to the -Ipath, and pass them all off to DMD to be compiled. Why can't DMD just do this itself, even just as an option? It could, and many people here wish it did. Maybe it even will someday. But right now it doesn't, so we have RDMD for that.
 I'm not sure if this is the right mailing list, but I'd really like to see
 rdmd using the $DFLAGS environment variable like dmd does.
Yea, that would be nice.
 For now, I'll use
 your handy shebang tip.

 Can future versions of rdmd turn on --shebang by default? I can't think of 
 a
 reason to give coders the ability to not support shebang options.
If it did that, then it won't work on the commandline anymore. :( IIRC, the problem is that with shebang scripts, all the args get passed in together as *one* large arg. But maybe there's a way to detect what's happening that isn't too unreliable...? Hell, other Unix apps don't seem to have this sort of problem, how the heck to they handle it?
 Jesse, aye, DFLAGS in dmd.conf appears to override the default rather than
 append to the default. And that's just silly.
Oct 27 2011
parent Andrew Pennebaker <andrew.pennebaker gmail.com> writes:
Nick, thanks for the in-depth explanation of compilation with C and D.

Other shebanged languages *do* have the argument limitation problem. One way
to deal with it is to use multiline
shebangs<http://rosettacode.org/wiki/Multiline_shebang>.
They're especially helpful for doing scripted
main<http://rosettacode.org/wiki/Scripted_Main>,
running main() when the script is run, but not when the code is imported by
other code.

For example, since Clojure is in Java Land, it expects a class name rather
than a filename, so you have to do shell trickery just to get the basename.

Clojure

":";exec clj -m `basename $0 .clj` $0 ${1+"$ "}
":";exit


The CLISP implementation of Common Lisp drops the program name as an
argument, so you have to forcibly add it back. Unfortunately, each CL
implementation has its own program name, *and* command line semantics, so
you have to rewrite this one for the particular CL implementation on your
machine.

Common Lisp

#!/bin/sh
#|
exec clisp -q -q $0 $0 ${1+"$ "}

exit
|#


Chicken Scheme

#!/bin/sh
#|
exec csi -ss $0 ${1+"$ "}

exit
|#


Emacs Lisp

:;exec emacs -batch -l $0 -f main $*

Smalltalk

"exec" "gst" "-f" "$0" "$0" "$ "
"exit"


The trick is to find a way to comment the shebang lines so that sh sees them
but not your programming language. But the real trouble is discovering the
secret syntax for this; when you have to resort to multiline shebangs,
that's an indication that scripting/CLI/POSIX is an incredibly low priority,
so developers A) don't know such obscure syntax and B) don't understand why
anyone would want to script on the command line. Common Lispers tell you
"there's no reason to use bash when you've got the CL repl". Smalltalkers
say "just use the Squeak VM GUI." And Free Pascalers remark "Scripting? You
kids get off my lawn!"

Language-specific IDEs are neat, but I like using a language-agnostic
development environment: a text editor and a shell, and I like being able to
dot-slash my scripts: ./script if at all possible.

So three cheers for rdmd!

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Thu, Oct 27, 2011 at 11:17 PM, Nick Sabalausky <a a.a> wrote:

 "Andrew Pennebaker" <andrew.pennebaker gmail.com> wrote in message
 news:mailman.550.1319767813.24802.digitalmars-d puremagic.com...
 Nick, thanks for the info. I'm upgrading my Homebrew D installation now.
 What's the point of -Ipath for dmd if you still have to specify the
actual
 files in the path?
It has to do with D's C/C++ legacy, and the traditional C/C++ build model. In C/C++, you can compile difference sources separately, and *then* link them together - in fact, that's the old traditional way to do it: (I might not have these commands correct, I don't use gcc much) $ gcc -c -I~/ -I~/zlib a.c # compile to a.o, imports/headers can be found in ~/ and ~/zlib $ gcc -c ~/b.c # compile to b.o $ gcc -c ~/c.c # compile to c.o $ ld -of app a.o b.o c.o ~/zlib/zlib.lib # link together into app, along with pre-built zlib $ ./app # run app D retains that ability: $ dmd -c -I~/ -I~/zlib a.d # compile to a.o, imports/headers can be found in ~/ and ~/zlib $ dmd -c ~/b.d # compile to b.o $ dmd -c ~/c.d # compile to c.o $ dmd -ofapp a.o b.o c.o ~/zlib/zlib.lib # link together into app, along with pre-built zlib $ ./app # run app And as a shortcut, modern C/C++ and D compilers offer the ability to simplify that all into one command: $ dmd -ofapp -I~/zlib a.d ~/b.d ~/c.d ~/zlib/zlib.lib # shortcut for the above statements But the old way is still possible becuause sometimes it can be useful (for instance, if a b and c are all in different languages, or if you want them each compiled with different settings, or to speed up long C/C++ compile times by compiling different parts on different machines). So that leads to this: Regardless of whether you do that in C/C++ or D: Suppose 'a' imports 'b', and inside 'a' you call a function from 'b'. If you've told it to *only* compile 'a' and not 'b' (because you intend to do it all separately) how does the compiler know that function you're using actually exists if you've only given it 'a'? Or if 'a' uses a class defined in 'b', how does the compiler know what members the class has if you only told it to compile 'a'? It has to find 'b', open it, and check. That's what -Ipath is for, so it knows where to find 'b' so it can find out what's in 'b', so that it can compile 'a' regardless of whether or not it's actually compiling 'b' as well. Of course, in most cases with D, all of that "one at a time" junk is just a pointless PITA, so fortunately we have RDMD to find all the .d files and just shove them all off to be compiled. So this: $ dmd -ofapp -I~/zlib a.d ~/b.d ~/c.d ~/zlib/zlib.lib Becomes this: $ rdmd --build-only -ofapp -I~/zlib ~/zlib/zlib.lib a.d Note that ~/b.d and ~/c.d were omitted because RDMD will just find them itself, thanks to the -Ipath, and pass them all off to DMD to be compiled. Why can't DMD just do this itself, even just as an option? It could, and many people here wish it did. Maybe it even will someday. But right now it doesn't, so we have RDMD for that.
 I'm not sure if this is the right mailing list, but I'd really like to
see
 rdmd using the $DFLAGS environment variable like dmd does.
Yea, that would be nice.
 For now, I'll use
 your handy shebang tip.

 Can future versions of rdmd turn on --shebang by default? I can't think
of
 a
 reason to give coders the ability to not support shebang options.
If it did that, then it won't work on the commandline anymore. :( IIRC, the problem is that with shebang scripts, all the args get passed in together as *one* large arg. But maybe there's a way to detect what's happening that isn't too unreliable...? Hell, other Unix apps don't seem to have this sort of problem, how the heck to they handle it?
 Jesse, aye, DFLAGS in dmd.conf appears to override the default rather
than
 append to the default. And that's just silly.
Oct 28 2011