cps-org / cps

Common Package Specification — A cross-tool mechanism for locating software dependencies
https://cps-org.github.io/cps/
Other
91 stars 8 forks source link

`Location` vs `Link-Location` issues #34

Open dcbaker opened 4 months ago

dcbaker commented 4 months ago

The current state is that the tool doing the lookup needs to know what platform it is running for to know if it needs to point at Link-Location or Location, since on Windows you do not link with the .dll, but with the interface library, pointed at by Link-Location. On all other platforms you will link with the .so or .dylib, pointed at by by Location. This is especially burdensome when cross compiling, since now the tool needs to know what platform it going to be running for, not just on.

We can avoid all of this ambiguity by doing one of two things:

  1. Location should point to the library you will ink with, the implementation library on Windows, the shared object elsewhere
  2. whenever Location is provided Link-Location should also be provided, and point to the actual thing to link to, as above
dcbaker commented 4 months ago

Actually, thinking about this more and looking at the sample, it has this:

    "sample-shared": {
      "Type": "dylib",
      "Requires": [ ":sample-core" ],
      "Configurations": {
        "Optimized": {
          "Location": "@prefix@/lib64/libsample.so.1.2.0"
        },
        "Debug": {
          "Location": "@prefix@/lib64/libsample_d.so.1.2.0"
        }
      }
    }

Which isn't correct. We don't want to link with the .so.1.2.0, we want to link with the bare .so. So that makes me thing we should require the Link-Location to be set always. On !Windows it should point the bare .so or .dylib

mwoehlke commented 4 months ago

I think you're over-complicating things. The way this works is actually relatively simple:

If that's unclear in the specification, we can fix that, but note that nothing in the above cares what platform you're on, or targeting. The idea with the current implementation is that you don't need to specify both if they have the same value.

We don't want to link with the .so.1.2.0, we want to link with the bare .so. So that makes me thing we should require the Link-Location to be set always.

I am perhaps less savvy with respect to when you use the unversioned symlinks, but that sounds plausible if "require" is replaced with "specify as best practice for".

dcbaker commented 4 months ago

I'm not an expert on Windows, but you never link to the .dll, only the .lib, right?. If so there would never be a reason to specify the .dll, since you never pass it as a linking argument?

You should always link with the unversioned .so, the elf header in the .so will contain version requirement information, and at runtime ld.so will find a library that meets those requirements.

So, I guess the requirement for Linux should be either: Location points to the bare .so, or if it doesn't then Link-Location must be set.

mwoehlke commented 4 months ago

I'm not an expert on Windows, but you never link to the .dll, only the .lib, right?

Link, yes, but you load the .dll. There are instances in which you want to know both paths. (For one, if something is trying to do automatic PATH mangling. I'm pretty sure there are also cases where some projects' build systems do things like taking a target — that is, a component in CPS parlance — location and passing it as a command-line argument.)

So, I guess the requirement for Linux should be either: Location points to the bare .so, or if it doesn't then Link-Location must be set.

That sounds reasonable, except, again, I'm not sure it belongs in the CPS specification. Not as a stronger than a recommendation, in any case.

dcbaker commented 4 months ago

Link, yes, but you load the .dll. There are instances in which you want to know both paths. (For one, if something is trying to do automatic PATH mangling. I'm pretty sure there are also cases where some projects' build systems do things like taking a target — that is, a component in CPS parlance — location and passing it as a command-line argument.)

This makes me feel like we're specing backwards then. Link-Location should always be set, and must point at the thing you link to, and Location may be set, and point at a loaded component. But I'm not going to die on that hill

That sounds reasonable, except, again, I'm not sure it belongs in the CPS specification. Not as a stronger than a recommendation, in any case.

I think it does make sense to follow the standard for the OS. On nix pointing at a versioned .so will surprise people, and it will break because there is no guarantee that a particular versioned .so will be on the system even though a dependency might be there. In fact, on systems like debian and fedora the versioned so's are part of the runtime package and the unversioned are in the dev package, along with the .cps files, and it is sometimes possible to install the -dev package without the runtime pacakge. It's also not how any current dependency system works because almost all of those (including pkg-config) give -lfoo, which the compiler will interpret as {path}/libfoo.so, not libfoo.so.X.Y.Z. It also runs up against issues of the portability of X.Y.Z extensions, as some nix OSes have X.Y.Z, some have X.Y and some only have .X. It also breaks the intention of those versioned .so's, which are for the runtime loader, not for the compiler/linker, we should not be pointing the toolchain at them.

mwoehlke commented 4 months ago

This makes me feel like we're specing backwards then.

Perhaps. I'll concede that there is historical "baggage" present. OTOH, from a human-language point of view, it seems (to me, at least) more natural that you always have a location, but may or may not have a distinct link-location. Regardless, our options are to either require both attributes when they might have identical values, or pick one to be optional, which will fall back to the other if not set.

I think it does make sense to follow the standard...

Again, I'm mostly not disagreeing, I just feel that what you're describing is best practice and not something that should be expressed as a strict requirement. (Not at the specification level, anyway; the specification generally tries to avoid getting into the weeds of platform-specific details. A "how to use CPS on ELF platforms" document might be a different matter.) That said, if a CPS is present and mentions a specific versioned .so, that does imply that said artifact is present. Otherwise you have a stray .cps file without the relevant artifacts.

it is sometimes possible to install the -dev package without the runtime pacakge

Since the unversioned .so is normally a symlink to the versioned .so, I don't see how that would be possible that wouldn't constitute being "broken".

For that matter, it's not entirely clear what difference this makes, since the linker is going to see the same bytes, regardless.

dcbaker commented 4 months ago

Okay, then I would settle from "must" to "should" language like: "A compliant Link-Location must point to a location to be passed to the linker, this location should conform to the standards of the OS the CPS file is for". would something like that be acceptable?