-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow setting, archiver, C compiler flags and linker flags from commandline #549
Conversation
- Read Fortran compiler from FC (overwritten by FPM_COMPILER for compatibility) - Read Fortran compiler options from FFLAGS - Read C compiler from CC (remove FPM_C_COMPILER since it was never documented) - Read archiver from AR
Well, lets ask for general feedback now that there has been a lot more use of fpm(1) things might have changed since the last go-around(?) Not sure I am impartial enough to review this, as I had previous PRs to So I think some of the voices against doing this in the past should be On a more specific note do you really need separate functions to pull the Previous discussions included the pros and cons of the use of environment In a previous variant the variables were only used for an unknown The general preference seemed to be the use of unique FPM_* names instead The thought earlier was that the FPM_* names could be multiple Some compilers already make use of the same variable names and/or have Doing this through the manifest file encourages the proper arguments Another solution is/was the use of response files, so you can have Since one of the stated goals of fpm(1) is to easily generate a All that being said everything is working so far. Assuming the main I assume you are commonly using the same variables with Cmake(1) or some That being said, I will continue reviewing this as a go-forward proposal All the testing so far works. Would be interested in a discussion of |
PS; This time I used git clone https://github.com/fortran-lang/fpm
cd fpm
git fetch origin pull/549/head:pull_549
git checkout pull_549
fpm build # I already have an fpm(1) on this machine
git diff master |
There used to be a pop-up in the code button at the top right with the git instructions, but those have been removed after GitHub CLI was released. I use
|
Not sure if there is an advantage to one or the other right off the cuff, but missed "gh" being released. Installed it. Interesting. First thing that looks appealing is the issues command for listing and entering issues without having to type in these GUIs. Thanks. All the tests I have run so far are working, wondering about FFLAGS versus F90FLAGS, as FFLAGS is often associated with pre-F90 code; also what about LDFLAGS and CPPFLAGS, probably use more frequently than AR. What should be the criteria for which flags are supported? Out of curiosity I can a scan and out of several million lines of files related to Make and CMake these were the closest to "standard" names I could find in Fortran-related files (far more containing C-related names than I imaged at > 30/100, which seems out of sorts, but many Fortran projects are private, I suspect):
with the vast majority using similar names with "project" prefixes (often lowercase), which was also interesting. What it did show was there is a lot of variability in what names are used. |
I'm currently looking into meson and cmake to figure out which environment variables they support and conda-build for a number of environment variables which are usually set from a packager for a build system.
|
I see the main purpose of the flag options to add package independent options, like building against a custom sysroot when building relocatable packages. I think we could have a |
I don't recommend relying on these generic but common environment variables. One relevant discussion about this is in #444. I do think there is value in having a way to control fpm behavior independent of the package. And I like using environment variables. I would support this if we namespaced any fpm variable with This is a big design decision so I will request review from a few more people. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use env variables, I think we should not use the generic ones used by other tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My view is expressed in #444, I think any environment variables should be prefixed with FPM_
. Using FPM_FC
instead of FPM_COMPILER
is fine. Using FPM_CC
instead of FPM_C_COMPILER
is fine. And so on. I explained in #444 why, but I am happy to answer any questions.
My next comment is that if such an environment variable changes, say:
fpm build
export FPM_FC=ifort
fpm build
Then the second fpm build
should rebuild everything, because the FPM_FC
now points to a different compiler. Does this currently happen? If not, we need to fix things so that it does happen.
It looks like we might want to meet over video to brainstorm this.
I think there is merit in supporting the most common environment
variables in fpm, rather than rolling our own.
My motivation for this change is coming from my experience with
packaging fpm. Fpm could have the capability to work just as
fpm install --prefix "$PREFIX"
for quite a few package ecosystems. But right now it is just tedious,
because the packager has to remember that fpm works differently than
other build systems and fixup the environment first
export FPM_COMPILER="${FC}"
export FPM_C_COMPILER="${CC}"
fpm install --prefix "$PREFIX" --flag "${LDFLAGS} ${FFLAGS}"
Without fixing up the environment first, the build might be broken.
If you look into conda-build the Fortran environment variables are
already quite a few, I really would prefer to not add more to the list
with fpm.
|
That's a valid use case. We could fix it with:
I am really worried about this design if we enable it by default. In order to move forward, let's enable this behavior with an option. That way in the Conda build file the build will be trivial, and that way we are not stopping progress. However, we need to meet and design this properly. |
In the previous discussions the one that got the most likes was program demo_M_CLI2
use M_CLI2, only : set_args, sget, specified
use M_CLI2, only : filenames=>unnamed
character(len=:),allocatable :: env
call set_args(' -env " "')
env=sget('env')
if(specified('env'))write(*,*)'env is specified'
write(*,*)'env is ['//env//']', len(sget('env'))
end program demo_M_CLI2
! if -env not present environment variables are not used
! if -env present with no value use FPM_*
! if -env with NULL string use names CC, FC, LDFLAGS, FFLAGS,AR
! if -env with a value use that, allowing for individual sets per compiler, per ... That is, the fpm command did not use environment variables (that would be a change, as FPM_COMPILER has been around for a while now) by default, but if the -env flag were present it would use names with the FPM_ prefix if no value was given, else if any other value was given it would be used as a suffix with an underscore between the prefix and the supported names, unless the value was a null string, in which case the plain names would be used. If activiated, the specific one would be looked for and if not found the FPM_* name would be looked for. This would allow you to set up defaults for a specific compiler like IFORT_FC=ifort, IFORT_FFLAGS='....' or for a specific type of compile like PROFILE_FFLAGS='-pg -O0' and then enter fpm build -env PROFILE, or fpm build -env IFORT. There was debate on whether if a name was specified FPM_ should be the backup or not. So for the packaging option it would just be fpm install --prefix "$PREFIX" --env fpm build -env # would be equivalent to "fpm build -env FPM"
fpm build -env IFORT # would use IFORT_* instead of FPM_* names and the FC, FFLAGS, AR, LDFLAGS, ... values would be used. This works with the command parser because strings have to be declared as at least one space in SETARGS(3f) but when used a null string is allowed; also I also just use a default value no one would ever use, normally "#N#" and if the value is set to that but specified(3f) is .TRUE. I know the keyword was specified but no value. As has come up before about making sure the values are used to create a unique build this is already an issue with several compilers (or a feature, depending on what you want to do). The Intel compiler lets you specify prefix and suffix environment variables for the compile line, and allows for pointing to a config file. We used to use the config file extensively to set the defaults for the site to a specific set of parameters we found gave us highly reproducable values and good performance across multiple platforms, and also made static libraries the default. Very handy, (the white paper about which parameters to use is unfortunately not public but was worth it and I recommend others do that, as an aside). But it did cause problems with some COTS products that compiled Fortran (particularly ABAQUS) so you had to use modules or wrappers to turn it off in some cases. That is a bit of an aside, but it is worth noting several compilers have features that bypass the fpm feature of creating a unique build directory for each set of compiler options, but file-specific profiles will do that too; but I have thought about whether fpm needed a feature to unset such variables. In the previous discussions it was hoped that profiles would eliminate the need for environment variables to a large extent. A major appeal of fpm(1) is that a new user can start building projects virtually "out of the box". If we complicate usage with too many options to satisfy a small populations' needs such as making it easier to package we risk having some of the same complaints made against other packaging utilities from make(1) and cmake(1) on, that the learning curve for learning how to use the packager for developers is way to high. |
One option would be to allow specification entirely over the command
line, without any environment variable usage
fpm install --flag "$FFLAGS" --c-flag "$CFLAGS" \
--link-flag "$LDFLAGS" --compiler "$FC" --c-compiler "$CC" \
--archiver "$AR"
This might become a bit unwieldy in practice. But I don't see how we
can make this setup automatic in fpm, i.e. I don't think there is a way
to know whether the C compiler should be clang or gcc together with
gfortran.
Another option would be to make it opt-in to use environment variables:
fpm config toolchain.use-env=true
which could be saved in `~/.config/fpm/config.toml` or similar and maps
to
[toolchain]
use-env = true
Regarding changes in environment variables, changing the Fortran
compiler will trigger a rebuild. We currently don't track which
compiler is used for C, therefore changing FPM_C_COMPILER doesn't
trigger rebuilds right now (this can be considered a bug). A possible
fix would be to create a hash from our entire toolchain, instead of
just using the basename of the Fortran compiler and the hash of the
Fortran flags.
|
I would have suggested that we support the standard environment variables ( I've never been much of a fan of environment variables (hidden global state that affects the behavior of various commands), so I do think any options should be specifiable via the command line. I'm ok with having environment variables for those who like them. I'm not sure how much value putting these kinds of options into a global config file would have. I would think they would be more project specific than that. I did notice that this PR adds the |
- allow to set archiver and C compiler from command line
@awvwgk, would you be against only supporting the Then we can merge this PR, move on, you get what you want (almost, just adding one single option), I get what I want, and we can use it and see if we want to make the The issue with making |
There is an issue with the order of evaluation when using a option like
--use-env-variables, which would require some more restructuring of the
code.
Right now we are using that we can provide defaults to M_CLI2 and
populate those from the environment variables. This way the values are
correctly overwritten when the option is provided by the user. In this
setup we would only know after the fact that we are allowed to use the
environment variables as default.
Brad's suggestion was easy to try out, therefore I went ahead and
implemented it. For a command line switch I need a bit more time to get
the implementation done properly. I'm at a conference the whole week,
therefore I won't get my head free to work concentrated on a bigger
coding project, but I'll pick it up for sure once I'm back.
Also, my preference for this would actually be a global configuration
file where every user can opt-in once. This saves the work of rewriting
the logic in the CLI as well. And I kind of like the way the hierachy
between command line and environment variables just works naturally
with M_CLI2 right now.
My suggestion to move forward would be:
1. I remove the non-prefixed environment variables from this patch
2. We discuss and review this patch
3. I implement a global setting file and a git-config like CLI
4. We add the non-prefixed environment variables as opt-in
(maybe even allow to opt-out of environment variables alltogether)
I guess we should organize a call for next week with at least everybody
participating in this thread to discuss further, by then I will have
the implementations ready for comparison.
|
@awvwgk your plan works with me. A global settings file I think is fine. It's not there by default, but you can put it there and enable the non-prefixed environment variables to work. |
@certik @milancurcic would you like to organize a call to discuss this topic? |
Requested changes addressed
As discussed today, this PR will be limited to filling in the missing options for customizing the linker and C compiler flags as well as selecting a custom archiver. It also proposes environment variables for all those options which are prefixed with I want to keep this PR lean and focus on this single feature, once we agree on it I will build the other points we discussed here on top and open a separate PR. |
Related to this PR, I want to point attention to this issue: conda-forge/fpm-feedstock#7 I strongly suspect the reason the |
Yes, this issue might indeed be related to the fact that we currently have no way to pass C flags to the compiler. Maybe this patch is able to fix the cross-compiled MacOS/Arm64 binary on conda-forge. @certik Since you have a Mac, could you give this a try? I think you can run the MacOS/Arm64 cross-compiler with rosetta on your machine and directly verify the result. Not sure how easy it is to reproduce the conda-build setup this way, but most of the environment setup should be in the build log. If not we have to wait for the next release to see whether this was the cause. |
The easiest way to try the patch is to start a PR at the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following the discussion yesterday, I'm happy for this PR to move forward as it is.
The implementation looks good to me, thank you Sebastian @awvwgk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Looks good to me as is.
Thanks for reviewing. I'll go ahead and merge this patch. |
FPM_FC
or--compiler
(deprecateFPM_COMPILER
)FPM_FFLAGS
or--flag
FPM_CC
or--c-compiler
(deprecateFPM_C_COMPILER
)FPM_CFLAGS
or--c-flag
FPM_AR
or--archiver
FPM_LDFLAGS
or--link-flag
Closes #529