Skip to content

Commit d9d93c2

Browse files
authored
Merge pull request #892 from fortran-lang/fix-cpp
Fix bootstrapping on Windows
2 parents fc4ac0e + 49a6503 commit d9d93c2

File tree

10 files changed

+177
-83
lines changed

10 files changed

+177
-83
lines changed

src/fpm.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ subroutine build_model(model, settings, package, error)
4242
type(package_config_t) :: dependency
4343
character(len=:), allocatable :: manifest, lib_dir, flags, cflags, cxxflags, ldflags
4444
logical :: has_cpp
45-
logical :: duplicates_found = .false.
45+
logical :: duplicates_found
4646
type(string_t) :: include_dir
4747

4848
model%package_name = package%name
@@ -101,8 +101,7 @@ subroutine build_model(model, settings, package, error)
101101
associate(dep => model%deps%dep(i))
102102
manifest = join_path(dep%proj_dir, "fpm.toml")
103103

104-
call get_package_data(dependency, manifest, error, &
105-
apply_defaults=.true.)
104+
call get_package_data(dependency, manifest, error, apply_defaults=.true.)
106105
if (allocated(error)) exit
107106

108107
model%packages(i)%name = dependency%name
@@ -118,7 +117,7 @@ subroutine build_model(model, settings, package, error)
118117
if (dependency%preprocess(j)%name == "cpp") then
119118
if (.not. has_cpp) has_cpp = .true.
120119
if (allocated(dependency%preprocess(j)%macros)) then
121-
model%packages(i)%macros = dependency%preprocess(j)%macros
120+
model%packages(i)%macros = dependency%preprocess(j)%macros
122121
end if
123122
else
124123
write(stderr, '(a)') 'Warning: Preprocessor ' // package%preprocess(i)%name // &
@@ -249,6 +248,7 @@ subroutine build_model(model, settings, package, error)
249248
if (allocated(error)) return
250249

251250
! Check for duplicate modules
251+
duplicates_found = .false.
252252
call check_modules_for_duplicates(model, duplicates_found)
253253
if (duplicates_found) then
254254
call fpm_stop(1,'*build_model*:Error: One or more duplicate module names found.')

src/fpm/cmd/publish.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ subroutine cmd_publish(settings)
3535
type(downloader_t) :: downloader
3636
integer :: i
3737

38+
! Get package data to determine package version.
3839
call get_package_data(package, 'fpm.toml', error, apply_defaults=.true.)
3940
if (allocated(error)) call fpm_stop(1, '*cmd_build* Package error: '//error%message)
4041
version = package%version

src/fpm/manifest.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
!> Additionally, the required data types for users of this module are reexported
88
!> to hide the actual implementation details.
99
module fpm_manifest
10-
use fpm_manifest_build, only: build_config_t
1110
use fpm_manifest_example, only : example_config_t
1211
use fpm_manifest_executable, only : executable_config_t
1312
use fpm_manifest_dependency, only : dependency_config_t
1413
use fpm_manifest_library, only : library_config_t
15-
use fpm_mainfest_preprocess, only : preprocess_config_t
14+
use fpm_manifest_preprocess, only : preprocess_config_t
1615
use fpm_manifest_package, only : package_config_t, new_package
1716
use fpm_error, only : error_t, fatal_error
1817
use fpm_toml, only : toml_table, read_package_file
1918
use fpm_manifest_test, only : test_config_t
2019
use fpm_filesystem, only: join_path, exists, dirname, is_dir
20+
use fpm_environment, only: os_is_unix
2121
use fpm_strings, only: string_t
2222
implicit none
2323
private
@@ -109,7 +109,7 @@ subroutine get_package_data(package, file, error, apply_defaults)
109109
call read_package_file(table, file, error)
110110
if (allocated(error)) return
111111

112-
if (.not.allocated(table)) then
112+
if (.not. allocated(table)) then
113113
call fatal_error(error, "Unclassified error while reading: '"//file//"'")
114114
return
115115
end if

src/fpm/manifest/build.f90

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,7 @@ subroutine check(table, package_name, error)
153153
do ikey = 1, size(list)
154154
select case(list(ikey)%key)
155155

156-
case("auto-executables", "auto-examples", "auto-tests", "link", "external-modules")
157-
continue
158-
159-
case ("module-naming")
156+
case("auto-executables", "auto-examples", "auto-tests", "link", "external-modules", "module-naming")
160157
continue
161158

162159
case default

src/fpm/manifest/package.f90

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,11 @@ module fpm_manifest_package
4343
use fpm_manifest_library, only : library_config_t, new_library
4444
use fpm_manifest_install, only: install_config_t, new_install_config
4545
use fpm_manifest_test, only : test_config_t, new_test
46-
use fpm_mainfest_preprocess, only : preprocess_config_t, new_preprocessors
46+
use fpm_manifest_preprocess, only : preprocess_config_t, new_preprocessors
4747
use fpm_filesystem, only : exists, getline, join_path
4848
use fpm_error, only : error_t, fatal_error, syntax_error, bad_name_error
49-
use fpm_toml, only : toml_table, toml_array, toml_key, toml_stat, get_value, &
50-
& len
49+
use fpm_toml, only : toml_table, toml_array, toml_key, toml_stat, get_value, len
5150
use fpm_versioning, only : version_t, new_version
52-
use fpm_filesystem, only: join_path
5351
implicit none
5452
private
5553

src/fpm/manifest/preprocess.f90

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
!> macros = []
1111
!> ```
1212

13-
module fpm_mainfest_preprocess
13+
module fpm_manifest_preprocess
1414
use fpm_error, only : error_t, syntax_error
1515
use fpm_strings, only : string_t
1616
use fpm_toml, only : toml_table, toml_key, toml_stat, get_value, get_list
@@ -82,27 +82,17 @@ subroutine check(table, error)
8282

8383
character(len=:), allocatable :: name
8484
type(toml_key), allocatable :: list(:)
85-
logical :: suffixes_present, directories_present, macros_present
8685
integer :: ikey
8786

88-
suffixes_present = .false.
89-
directories_present = .false.
90-
macros_present = .false.
91-
9287
call table%get_key(name)
9388
call table%get_keys(list)
9489

9590
do ikey = 1, size(list)
9691
select case(list(ikey)%key)
97-
case default
98-
call syntax_error(error, "Key " // list(ikey)%key // "is not allowed in preprocessor"//name)
99-
exit
100-
case("suffixes")
101-
suffixes_present = .true.
102-
case("directories")
103-
directories_present = .true.
104-
case("macros")
105-
macros_present = .true.
92+
!> Valid keys.
93+
case("suffixes", "directories", "macros")
94+
case default
95+
call syntax_error(error, "Key '"//list(ikey)%key//"' not allowed in preprocessor '"//name//"'."); exit
10696
end select
10797
end do
10898
end subroutine check
@@ -191,4 +181,4 @@ subroutine info(self, unit, verbosity)
191181

192182
end subroutine info
193183

194-
end module fpm_mainfest_preprocess
184+
end module fpm_manifest_preprocess

src/fpm_compiler.F90

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -773,8 +773,6 @@ function get_id(compiler) result(id)
773773
character(len=*), intent(in) :: compiler
774774
integer(kind=compiler_enum) :: id
775775

776-
integer :: stat
777-
778776
if (check_compiler(compiler, "gfortran")) then
779777
id = id_gcc
780778
return

src/fpm_os.F90

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ module fpm_os
33
use fpm_filesystem, only: exists, join_path, get_home
44
use fpm_environment, only: os_is_unix
55
use fpm_error, only: error_t, fatal_error
6+
67
implicit none
78
private
8-
public :: change_directory, get_current_directory, get_absolute_path, convert_to_absolute_path
9+
public :: change_directory, get_current_directory, get_absolute_path, convert_to_absolute_path, &
10+
& get_absolute_path_by_cd
911

1012
integer(c_int), parameter :: buffersize = 1000_c_int
1113

@@ -47,8 +49,18 @@ function realpath(path, resolved_path) result(ptr) bind(C)
4749
type(c_ptr) :: ptr
4850
end function realpath
4951

52+
!> Determine the absolute, canonicalized path for a given path. Windows-only.
53+
function fullpath(resolved_path, path, maxLength) result(ptr) bind(C, name="_fullpath")
54+
import :: c_ptr, c_char, c_int
55+
character(kind=c_char, len=1), intent(in) :: path(*)
56+
character(kind=c_char, len=1), intent(out) :: resolved_path(*)
57+
integer(c_int), value, intent(in) :: maxLength
58+
type(c_ptr) :: ptr
59+
end function fullpath
60+
5061
!> Determine the absolute, canonicalized path for a given path.
51-
!> Calls custom C routine and is able to distinguish between Unix and Windows.
62+
!> Calls custom C routine because the `_WIN32` macro is correctly exported
63+
!> in C using `gfortran`.
5264
function c_realpath(path, resolved_path, maxLength) result(ptr) &
5365
bind(C, name="c_realpath")
5466
import :: c_ptr, c_char, c_int
@@ -126,6 +138,10 @@ subroutine c_f_character(rhs, lhs)
126138
end subroutine c_f_character
127139

128140
!> Determine the canonical, absolute path for the given path.
141+
!>
142+
!> Calls a C routine that uses the `_WIN32` macro to determine the correct function.
143+
!>
144+
!> Cannot be used in bootstrap mode.
129145
subroutine get_realpath(path, real_path, error)
130146
character(len=*), intent(in) :: path
131147
character(len=:), allocatable, intent(out) :: real_path
@@ -145,10 +161,7 @@ subroutine get_realpath(path, real_path, error)
145161

146162
allocate (cpath(buffersize))
147163

148-
! The _WIN32 macro is currently not exported using gfortran.
149-
#if defined(FPM_BOOTSTRAP) && !defined(_WIN32)
150-
ptr = realpath(appended_path, cpath)
151-
#else
164+
#ifndef FPM_BOOTSTRAP
152165
ptr = c_realpath(appended_path, cpath, buffersize)
153166
#endif
154167

@@ -158,7 +171,7 @@ subroutine get_realpath(path, real_path, error)
158171
call fatal_error(error, "Failed to retrieve absolute path for '"//path//"'.")
159172
end if
160173

161-
end subroutine get_realpath
174+
end subroutine
162175

163176
!> Determine the canonical, absolute path for the given path.
164177
!> Expands home folder (~) on both Unix and Windows.
@@ -169,49 +182,66 @@ subroutine get_absolute_path(path, absolute_path, error)
169182

170183
character(len=:), allocatable :: home
171184

185+
#ifdef FPM_BOOTSTRAP
186+
call get_absolute_path_by_cd(path, absolute_path, error); return
187+
#endif
188+
172189
if (len_trim(path) < 1) then
173-
! Empty path
174-
call fatal_error(error, 'Path cannot be empty')
175-
return
190+
call fatal_error(error, 'Path cannot be empty'); return
176191
else if (path(1:1) == '~') then
177-
! Expand home
178192
call get_home(home, error)
179193
if (allocated(error)) return
180194

181195
if (len_trim(path) == 1) then
182-
absolute_path = home
183-
return
196+
absolute_path = home; return
184197
end if
185198

186199
if (os_is_unix()) then
187200
if (path(2:2) /= '/') then
188-
call fatal_error(error, "Wrong separator in path: '"//path//"'")
189-
return
201+
call fatal_error(error, "Wrong separator in path: '"//path//"'"); return
190202
end if
191203
else
192204
if (path(2:2) /= '\') then
193-
call fatal_error(error, "Wrong separator in path: '"//path//"'")
194-
return
205+
call fatal_error(error, "Wrong separator in path: '"//path//"'"); return
195206
end if
196207
end if
197208

198209
if (len_trim(path) == 2) then
199-
absolute_path = home
200-
return
210+
absolute_path = home; return
201211
end if
202212

203213
absolute_path = join_path(home, path(3:len_trim(path)))
204214

205215
if (.not. exists(absolute_path)) then
206-
call fatal_error(error, "Path not found: '"//absolute_path//"'")
207-
deallocate (absolute_path)
208-
return
216+
call fatal_error(error, "Path not found: '"//absolute_path//"'"); return
209217
end if
210218
else
211219
! Get canonicalized absolute path from either the absolute or the relative path.
212220
call get_realpath(path, absolute_path, error)
213221
end if
222+
end subroutine
223+
224+
!> Alternative to `get_absolute_path` that uses `chdir`/`_chdir` to determine the absolute path.
225+
!>
226+
!> `get_absolute_path` is preferred but `get_absolute_path_by_cd` can be used in bootstrap mode.
227+
subroutine get_absolute_path_by_cd(path, absolute_path, error)
228+
character(len=*), intent(in) :: path
229+
character(len=:), allocatable, intent(out) :: absolute_path
230+
type(error_t), allocatable, intent(out) :: error
231+
232+
character(len=:), allocatable :: current_path
233+
234+
call get_current_directory(current_path, error)
235+
if (allocated(error)) return
236+
237+
call change_directory(path, error)
238+
if (allocated(error)) return
239+
240+
call get_current_directory(absolute_path, error)
241+
if (allocated(error)) return
214242

243+
call change_directory(current_path, error)
244+
if (allocated(error)) return
215245
end subroutine
216246

217247
!> Converts a path to an absolute, canonical path.

test/fpm_test/test_manifest.f90

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ subroutine collect_manifest(tests)
7070
& new_unittest("preprocess-wrongkey", test_preprocess_wrongkey, should_fail=.true.), &
7171
& new_unittest("preprocessors-empty", test_preprocessors_empty, should_fail=.true.), &
7272
& new_unittest("macro-parsing", test_macro_parsing, should_fail=.false.), &
73-
& new_unittest("macro-parsing-dependency", test_macro_parsing_dependency, should_fail=.false.)]
73+
& new_unittest("macro-parsing-dependency", test_macro_parsing_dependency, should_fail=.false.) &
74+
& ]
7475

7576
end subroutine collect_manifest
7677

@@ -669,26 +670,26 @@ subroutine test_build_valid(error)
669670
& 'name = "example"', &
670671
& '[build]', &
671672
& 'auto-executables = false', &
672-
& 'auto-tests = false ', &
673-
& 'module-naming = true '
673+
& 'auto-tests = false', &
674+
& 'module-naming = true'
674675
close(unit)
675676

676677
call get_package_data(package, temp_file, error)
677678

678679
if (allocated(error)) return
679680

680681
if (package%build%auto_executables) then
681-
call test_failed(error, "Wong value of 'auto-executables' read, expecting .false.")
682+
call test_failed(error, "Wrong value of 'auto-executables' read, expecting .false.")
682683
return
683684
end if
684685

685686
if (package%build%auto_tests) then
686-
call test_failed(error, "Wong value of 'auto-tests' read, expecting .false.")
687+
call test_failed(error, "Wrong value of 'auto-tests' read, expecting .false.")
687688
return
688689
end if
689690

690-
if (.not.package%build%module_naming) then
691-
call test_failed(error, "Wong value of 'module-naming' read, expecting .true.")
691+
if (.not. package%build%module_naming) then
692+
call test_failed(error, "Wrong value of 'module-naming' read, expecting .true.")
692693
return
693694
end if
694695

@@ -765,17 +766,17 @@ subroutine test_build_empty(error)
765766
if (allocated(error)) return
766767

767768
if (.not.package%build%auto_executables) then
768-
call test_failed(error, "Wong default value of 'auto-executables' read, expecting .true.")
769+
call test_failed(error, "Wrong default value of 'auto-executables' read, expecting .true.")
769770
return
770771
end if
771772

772773
if (.not.package%build%auto_tests) then
773-
call test_failed(error, "Wong default value of 'auto-tests' read, expecting .true.")
774+
call test_failed(error, "Wrong default value of 'auto-tests' read, expecting .true.")
774775
return
775776
end if
776777

777778
if (package%build%module_naming) then
778-
call test_failed(error, "Wong default value of 'module-naming' read, expecting .false.")
779+
call test_failed(error, "Wrong default value of 'module-naming' read, expecting .false.")
779780
return
780781
end if
781782

@@ -1318,7 +1319,7 @@ subroutine test_install_wrongkey(error)
13181319
end subroutine test_install_wrongkey
13191320

13201321
subroutine test_preprocess_empty(error)
1321-
use fpm_mainfest_preprocess
1322+
use fpm_manifest_preprocess
13221323
use fpm_toml, only : new_table, toml_table
13231324

13241325
!> Error handling
@@ -1336,7 +1337,7 @@ end subroutine test_preprocess_empty
13361337

13371338
!> Pass a TOML table with not allowed keys
13381339
subroutine test_preprocess_wrongkey(error)
1339-
use fpm_mainfest_preprocess
1340+
use fpm_manifest_preprocess
13401341
use fpm_toml, only : new_table, add_table, toml_table
13411342

13421343
!> Error handling
@@ -1357,7 +1358,7 @@ end subroutine test_preprocess_wrongkey
13571358

13581359
!> Preprocess table cannot be empty.
13591360
subroutine test_preprocessors_empty(error)
1360-
use fpm_mainfest_preprocess
1361+
use fpm_manifest_preprocess
13611362
use fpm_toml, only : new_table, toml_table
13621363

13631364
!> Error handling

0 commit comments

Comments
 (0)