fortran-lang / fpm

Fortran Package Manager (fpm)
https://fpm.fortran-lang.org
MIT License
874 stars 99 forks source link

Command line argument to specify manifest location #611

Open rouson opened 2 years ago

rouson commented 2 years ago

Description

I'm building a project that depends on GASNet-EX, which links to different libraries on different operating systems (macOS vs Linux). We will need different OS-specific fpm.toml files.

Possible Solution

It would be helpful to have a fpm argument that specifies which manifest to use, e.g.,

fpm build --manifest macOS-fpm.toml

Additional Information

No response

awvwgk commented 2 years ago

Would it be an option to have operating system dependent link options in the same manifest? I would prefer to keep a single, somewhat more complex manifest rather than having several package manifest files, since those will cause issues for dependencies.

Maybe something like the selector below would be straight-forward to support in fpm:

[build]
link.osx = ["..."]
link.linux = ["..."]

Alternatively, there might be an option to use, which could provide a more general and extensible selector syntax

[build]
link = [
  {if="os is osx", then="..."},
]

However we will need to invent our own grammar or borrow an existing one and create an expression parser.

jvdp1 commented 2 years ago

Actually this might be also useful for supporting multiple compilers. E.g., I am currently trying fpm with 2 different compilers to build a same project. However, the libraries used by each compiler have slightly different names (e.g., "gomp" vs "iomp"). Therefore, if I want to use another compiler than the default one, I must first change the link option in fpm.toml (I didn't find a way to do that yet).

Le mer. 17 nov. 2021 à 22:39, Sebastian Ehlert @.***> a écrit :

Would it be an option to have operating system dependent link options in the same manifest? I would prefer to keep a single, somewhat more complex manifest rather than having several package manifest files, since those will cause issues for dependencies.

Maybe something like the selector below would be straight-forward to support in fpm:

[build]link.osx = ["..."]link.linux = ["..."]

Alternatively, there might be an option to use, which could provide a more general and extensible selector syntax

[build]link = [ {if="os is osx", then="..."}, ]

However we will need to invent our own grammar or borrow an existing one and create an expression parser.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/fortran-lang/fpm/issues/611#issuecomment-972077896, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD5RO7HX2GTWGUXE5MJH32DUMQOH5ANCNFSM5IIBAD6Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

urbanjost commented 2 years ago

I am also finding the lack of conditional expressions in a TOML file frustrating, but having profiles supported with definitions in the fpm.toml would satisfy most of my needs.

If there were a standard pre-processor another solution might be that the fpm.toml file could be run through the pre-processor passing in the current OS and compiler and profile. Not the most elegant solution but it not require any additional coding if something like cpp(1) directives were supported.

Is there any other program using TOML files that has added conditional processing other than via selecting named sections?

ivan-pi commented 2 years ago

Couldn't fpm have a built-in expression parser to evaluate some type of Fortran-inspired conditional statements? Something like:

link = [ 'merge("iomp","gomp",compiler == id_intel)' ]

The first suggestion from @awvwgk looks like the simplest to me. On the other hand the combinatorial explosion of platforms, compilers, and various library name exceptions, makes me worried it could get complicated, and a solution at a higher abstraction level is needed.

An orthogonal suggestion would be to have the main fpm.toml which includes the default options, and secondary platform specific toml files, which get loaded after the primary toml, overwriting any values. (Doesn't CMake use an approach like this?)

rouson commented 2 years ago

I'm fine with any solution that solves the problem. I suspect that the one I originally proposed is probably the easiest for fpm to support, albeit by offloading to the user the work of maintaining multiple manifests. I'm a minimalist so I use default directory locations, my projects only have a few dependencies, and my manifests are generally 5-10 lines. Maintaining multiple ones is no problem.

Of the other solutions proposed, I think the conditional logic seems like the most work to implement in fpm, whereas the preprocessor approach adds a third-party tool and I think one of the most beautiful things about fpm is that it has no dependencies other than a Fortran compiler and it can be installed by compiling a single file. I recommend keeping that level of simplicity as long as you possibly can. When trying to introduce fpm in a project that was using another build system, the simplicity with which fpm can be installed and used is a major plus.

rouson commented 2 years ago

Another alternative would be an option to specify the manifest's location. For now, I will have the project's install.sh script create an OS-specific manifest in the build tree and then create a soft-link to that manifest at the top level of the source tree. If something like a --manifest-path existed, we wouldn't need the soft-link, which would eliminate the chance that someone might unnecessarily commit the link. For now, I'll add fpm.toml to the .gitignore file, but that feels a little strange and might cause some headache someday if we're able to write a single manifest for all platforms and a future developer can't figure out why they can't commit the new manifest. I'm likely to be that forgetful future developer. :)

dalon-work commented 2 years ago

The manifest file for fpm appears to be loosely based on Rust's Cargo.toml files. You can find an example of changing flags based on the OS here: https://doc.rust-lang.org/cargo/reference/config.html#configuration-format. It seems they use the . syntax. Of course, they only have to worry about a single compiler, but I think the idea can be extended.

ShinobuAmasaki commented 7 months ago

I am also facing a similar issue, namely the need to switch the linked libraries depending on the OS of the build environment.

I propose the following approach:

In this method, we introduce a [[target]] table array to the manifest, which accepts lists for os, compiler, and link. It takes the following form:

[[target]]
os = "*"
compiler = "*"
link = ["alice"]

[[target]]
os = ["linux"]
compiler = "*"
link = ["bob", "carol"]

[[target]]
os = ["windows"]
compier = ["ifx", "ifort"]
link = ["dave"]

Here, os and compiler act as "conditional values" for the build. If they match the condition, items from the link list are added to the linker's instructions. In this instance, if using the Intel's compiler on Windows, alice dave will be added to the instructions. On the other hand, if using any compiler on Linux OS, alice bob carol will be added to the instructions.

This approach enhances how fpm handles Fortran-specific challenges by considering not only the OS but also numerous compilers. Additionally, the ability to add new attributes for the target with a minimal format is seems to be a positive aspect (for example, when switching instructions based on CPU architectures).