For the one that doesn't work, if we look at the
ls -l result, we get the following:
[sparticvs@sparta test]$ ls -l build/
lrwxrwxrwx. 1 sparticvs sparticvs 6 Dec 17 16:08 client -> client
Now to understand what is going on here. Let's look at the command you called:
ln -s client build/client
According to the Man Page, there are two possible matches for this format
ln [OPTION]... [-T] TARGET LINK_NAME (1st form)
ln [OPTION]... TARGET... DIRECTORY (3rd form)
It will match on the first form (since its first). Now, the "target name" or
client in your case, can be (according to the complete
ln manual) arbitrary strings. The don't have to resolve to anything right now, but can resolve to something in the future. What you are creating with your invocation is a "dangling symlink" and the system does not keep you from creating these.
Now your second invocation
ln -s ../client build/client is what is called a "relative symlink" (as you noted in your own post). There is a second type and that is an "absolute symlink" which would be called by doing
ln -s /home/user/client build/client.
This is not a bug. According to the manual it states:
When creating a relative symlink in a different location than the
current directory, the resolution of the symlink will be different
than the resolution of the same string from the current directory.
Therefore, many users prefer to first change directories to the
location where the relative symlink will be created, so that
tab-completion or other file resolution will find the same target as
what will be placed in the symlink.
info coreutils 'ln invocation'
That said, you MUST use either the relative or absolute path to the target.