-
Notifications
You must be signed in to change notification settings - Fork 111
Fix bootstrapping on Windows #892
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
Conversation
Well, I obviously have to fix the tests, but you could still check if it builds on Windows. |
Currently, manually declare the FPM_IS_WINDOWS macro with the following command, fpm compiles normally on Windows: > fpm -v
Version: 0.8.1, alpha
***
OS Type: Windows
> fpm build --flag "-DFPM_IS_WINDOWS"
***
install.f90 done.
main.f90 done.
libfpm.a done.
fpm.exe done.
[100%] Project compiled successfully. |
Thanks for checking! That's a good start :) |
Could you please try it again on Windows without the manual flag? I still don't understand why the CI is still not getting it, though. I thought that the change should be registered in bootstrapping mode. 🤔 |
I think if we don't use FPM_IS_WINDOWS, we will definitely fail to compile on Windows. |
In my understanding, bootstrapping means that we're compiling and running |
It seems that the
The first step needs to manually set the macro definition |
Ah, yes. Ok, I just put back the C routine, which is used when we're not bootstrapping, and then we differentiate between Windows and Unix using |
src/fpm/manifest.f90
Outdated
type(toml_table), allocatable :: table | ||
character(len=:), allocatable :: root | ||
logical :: set_is_windows_macro = .true. |
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.
Please help me understand here. Are we adding the FPM_IS_WINDOWS
macro by default to every package that fpm is going to ever build?
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.
In the beginning, I added it to the root package only, but it didn't work (it wasn't registered during compilation). Maybe the reason is that the root package is also added to the dependency tree and that's the place where the macro matters. It worked when I exported it for every dependency in the dependency tree. I did so also because I didn't want to differentiate between the root package and all the other dependencies in the dependency tree.
If you have any better idea, let me know. I'll see if I can add the dependency to the dependency tree with the flag in place.
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.
Yes, I had a look again. get_package_data
is called on every package of the dependency tree (again) and that's where the macro needs to be set for the root package. So if I did this, it works:
if (i == 1) then
call get_package_data(dependency, manifest, error, apply_defaults=.true., add_is_windows_macro=.true.)
else
call get_package_data(dependency, manifest, error, apply_defaults=.true., add_is_windows_macro=.false.)
end if
So I'm open for better suggestions.
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.
What we could do is add an opt-in instead of an opt-out. Meaning that we could add an export-windows-macro
flag to the [build]
config, for example, and set it to true
in the fpm
manifest:
[build]
export-windows-macro = true
That way we won't "pollute" any procedures, and it will only registered for the root package. How do you feel about this solution? @awvwgk @perazz
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 understanding is that minGW/MSYS compilers don't have access to realpath
on Windows. So I would start looking for a kiss fix first. What would happen if we just extended this for macros _WIN64
, __MINGW32__
, __MSYS__
, __MINGW64__
:
Lines 11 to 15 in fc4ac0e
#ifndef _WIN32 | |
return realpath(path, resolved_path); | |
#else | |
return _fullpath(resolved_path, path, maxLength); | |
#endif |
It's probably _WIN64
what we're looking for:
https://github.com/Alexpux/mingw-w64/blob/d0d7f784833bbb0b2d279310ddc6afb52fe47a46/mingw-w64-headers/crt/_cygwin.h#L28-L34
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.
That part of the code has so far not been a problem, but the bootstrapping is. If that part of the code you're referring to needs a fix, I'm happy to open another PR in the future.
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.
@minhqdao @zoziha please take a look at this approach:
main...perazz:fpm:test_windows_macros
I can't test it on msys2 right now (the CI has minGW64) but I believe it should work.
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.
@perazz The gfortran
compiler only presets the macro definition __GFORTRAN__
, other macro definitions such as _WIN32
, _WIN64
, __MINGW64__
are not preset.
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.
What gfortran provider on Windows has this issue? I understood it is from MSYS, or is it another installation? If it is minGW or MSYS, then some of those macros should be defined I believe.
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.
The previous Fortran standards did not specify preprocessors, and Fortran should not support preprocessors, but compiler manufacturers still adapted C preprocessors for Fortran. GCC (C/C++ language compiler) has these preset macro definitions, while gfortran does not, and I haven't seen any gfortran providers (msys, cygwin, mingw) on Windows preset macro definition _WIN32.
@minhqdao The mingw-w64-fpm package in MSYS2 uses the single-source-file version, which does not use any C source files other than the C standard library, but only a single > fpm build
[100%] Project compiled successfully.
> fpm build --flag "-DFPM_IS_WINDOWS"
[100%] Project compiled successfully.
> fpm build --flag "-DFPM_BOOTSTRAP"
fpm.exe failed.
[100%] Compiling...
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: build\gfortran_DE26B7BFDD5D0589\fpm\libfpm.a(src_fpm_os.F90.o):fpm_os.F90:(.text+0xf03): undefined reference to `realpath'
collect2.exe: error: ld returned 1 exit status
<ERROR> Compilation failed for object " fpm.exe "
<ERROR>stopping due to failed compilation
STOP 1
> fpm build --flag "-DFPM_BOOTSTRAP -DFPM_IS_WINDOWS"
[100%] Project compiled successfully. Since the Should fpm predefine |
Thanks for checking thoroughly, @zoziha. I once tried to let It's strange that in MSYS2 the call to |
At the same time, I was wondering, as fpm becomes more available for OS operations since we start using C sources (e.g., Links |
The single source is crucial for bootstrapping, in most scenarios we cannot rely on having an fpm executable around for building unless we can provide another way to bootstrap fpm, e.g. via another build system. |
If you are using I'm running |
I now moved the flag to: [preprocessor]
[preprocessor.example]
export-windows-macro = true The default is I think that's better but we'd need another release for it to build. |
I think we are derailing here a bit, the current solution does not look well designed to me. Let's step back and have another look on the problem, please. We have two scenarios here:
For (1) we should be able to find a solution using the A better option might be to export this information for all platforms / architectures using [preprocessor.cpp]
macros = [
"FPM_PLATFORM={platform}",
"FPM_ARCH={arch}"
] Note that we cannot rely on those guards in bootstrapping mode (1) because we cannot determine those in a reliable way without manual intervention. So those have to be used with care unless we find an alternative for our current bootstrapping strategy. |
src/fpm/manifest.f90
Outdated
@@ -126,6 +126,8 @@ subroutine get_package_data(package, file, error, apply_defaults) | |||
end if | |||
end if | |||
|
|||
call add_fpm_is_windows_macro(package%preprocess) |
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.
I know cargo
supports identifying the OS and selectively compiling the code, and it seems like fpm
can do something similar with this PR. (fpm
also knows the operating system type when it compiles the code.)
For me, this solution does not look so much different from What I don't understand, however, is the "manual intervention" part. Considering the bootstrapping issue, we could also get the absolute path by changing directories and running One could also use the command line interface, but I don't think that |
Please check once again if bootstrapping works on Windows. I hope that does so we can close this chapter at least for a while. @zoziha |
Thanks for your sharing @minhqdao . All the following commands have been successfully tested: > fpm build --flag "-DFPM_BOOTSTRAP -DFPM_IS_WINDOWS"
> fpm build --flag "-DFPM_BOOTSTRAP"
> fpm build --flag "-DFPM_IS_WINDOWS"
> fpm build |
Address #891.
Bootstrapping currently doesn't work on Windows using
gfortran
because the_WIN32
macro isn't exported by the compiler. This is an attempt to fix it by lettingfpm
export theFPM_IS_WINDOWS
macro.@zoziha @arteevraina @henilp105 @awvwgk