On Sun, Feb 28, 2021 at 10:06 PM bjornbytes <[email protected]> wrote:

> Hello, I have a project that builds some smaller modules into shared
> libraries, and then copies those DLL files to the same folder as the final
> executable.  I'm having trouble copying those libraries on windows when
> they are nested in subfolders.
>
> Here is a minimal project that illustrates the issue:
>
>   > dir /B /S
>   C:\test\a
>   C:\test\a\b
>   C:\test\a\b\c
>   C:\test\Tupfile
>
>   > more a\b\c
>   hi
>
>   > more Tupfile
>   : a/b/c |> copy %f %o |> d/e/f
>
> Attempting to build this results in the following:
>
>   tup error: failed to create child process: No such file or directory
>
> It took me some time to figure out that copy is not actually an exe file
> that exists in the PATH, but is instead a built in command.  I had to
> change the Tupfile to run the command inside cmd:
>
>   : a/b/c |> cmd /c copy %f %o |> d/e/f
>
> Now copy runs but it doesn't work properly because I'm using the wrong
> slashes.  I tried another change:
>
>   : a\b\c |> cmd /c copy %f %o |> d\e\f
>
> But tup invokes my command like this:
>
>   cmd /c copy a\b/c d\e\f
>
> Which understandably prints out "The syntax of the command is
> incorrect.".  I don't really fault tup for this or expect it to support the
> ugly windows slashes, but this could also be a bug, not sure.  At this
> point I think I'm stuck.  Questions/thoughts:
>
>    - Am I doing something wrong?  Is there an easier way to do this on
>    windows or a way to work around it?  I could maybe install some packages
>    (wsl/msys) that provide a sane unix cp, but I'm distributing this to others
>    and would prefer it to minimize its dependencies.
>
> Nope, you're not doing something wrong here. Unix cp via msys/mingw (and
probably wsl) should work, though I understand your concern of not wanting
to require other dependencies, especially for something as minimal as
copying a file. This is definitely something that should work with tup
out-of-the box.

>
>    - Should tup run commands inside a shell on windows?  I saw that there
>    was a COMSPEC environment variable that has the path to cmd.exe, maybe that
>    would be useful.
>
> It does run some commands using a cmd / bourne / bash shell depending on a
few parameters:

1) Bash is used if the ^b flag is specified in the Tupfile (eg: |> ^b^
bashcmd |> )
2) Bourne shell (sh) is used if a ./ or a back-quote ` is in the command
string
3) Windows command shell (cmd) is used if there are redirections/pipes with
the &, |, <, or > characters
4) Otherwise, the command string is passed to CreateProcess() as-is with no
shell added.

This is done in src/tup/server/windepfile.c in server_exec(). I think it
would be reasonable here to look for built-in cmd-shell commands and make
sure cmd is in the string as well, rather than rely on the developer
specifying it in the Tupfile.

>
>    - I see that errno is used to try to provide better error messages
>    when commands fail on windows, but perhaps this could be expanded.  I was
>    stuck on the "no such file or directory" message for a while because I
>    thought the paths provided to the copy command were invalid.
>
> I agree this could use some work.

>
>    - Is this indeed an issue with path separators on windows?
>
> Tup does a lot of work to make sure it is path-separator independent on
Windows with regards to the paths it gets from file accesses. In other
words, an open("foo/bar") and an open("foo\bar") in a subprogram would both
result in tup getting a dependency on the same underlying file "bar" in the
"foo" directory.

However, path-separators are more geared towards '/' in the parser, and '\'
is used as an escape character to do things like escape spaces in paths. So
you can't write a\b\c directly as a path in the Tupfile, it would need to
be a\\b\\c. Although this is not ideal for native Windows users, I think it
is reasonable for tup since its native internal path separator is '/'.

Whether or not paths are written with / or \ in the Tupfile itself, it
still needs to work in the underlying command. Certainly a\b/c is obviously
wrong :). Internally, tup separates filenames like a/b/c into a path part
and a file part, so this would get split into a path of "a/b" and a file of
"c". The '/' here gets put in by parser.c:set_path(), while the directory
part is copied directly from what the Tupfile says. Probably what needs to
happen is for tup to make sure that all paths are using '/' internally, and
then when a cmd-shell invocation is detected, it can swap them for '\'.
Does that sound reasonable?

I can submit pull requests for some of this stuff if that's helpful.
>

Sure, that would definitely be helpful to make sure it ends up working for
your real project. I think most of the work of fixing \ would be in
parser.c, while the error-handling and prefixing with cmd would be in
windepfile.c (though prefixing with cmd could instead be detected and done
in the parser, perhaps).

Thanks for the report!

-Mike

-- 
-- 
tup-users mailing list
email: [email protected]
unsubscribe: [email protected]
options: http://groups.google.com/group/tup-users?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"tup-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/tup-users/CA%2B6x0LX8Z8XKwwwjhUz4RZ1uONR%2BenJs3NDEE70%2Bb0rMokw2WQ%40mail.gmail.com.

Reply via email to