rust-fitsio icon indicating copy to clipboard operation
rust-fitsio copied to clipboard

Switch from Autotools to CMake for fitsio-sys

Open zec opened this issue 9 months ago • 9 comments

The current Autotools-based build process for the CFITSIO library in fitsio-sys (when enabled with the fitsio-src feature) requires an in-tree build, i.e., the .o files are placed in the same directory as the respective .c files. This leads to build failures when using fitsio from crates.io when it is built for multiple platforms—at least not without the remediation of removing the .o files, Makefile, etc. from ~/.cargo/registry/src in between builds, which is a bad developer experience.

This pull request switches from the Autotools-based build to using the alternative CMake-based build for CFITSIO. At the expense of requiring CMake to be installed, this allows for out-of-tree builds of CFITSIO, making multiple cross-compilations possible without needing a non-obvious remediation step.

zec avatar Mar 21 '25 05:03 zec

Is it possiable to support MSVC native compile on Windows platform? Compared with autotools, CMake is cross platfrom supported includes native MSVC.

GuoHaoxuan avatar Mar 26 '25 17:03 GuoHaoxuan

That is supported by the cmake crate by setting the CMAKE_GENERATOR environment variable [1] for the Cargo invocation.

[1] https://docs.rs/cmake/0.1.54/cmake/struct.Config.html#method.generator

zec avatar Mar 26 '25 19:03 zec

Thanks for posting this PR. I am not convinced replacing one build system with another is the answer. I feel it is less likely that a user has cmake than has the autotools suite (really just make since the configure script has been created already).

I have been doing some investigation. autootols (specifically the Rust crate) supports out-of-tree builds already, however we are using a version of cfitsio that is too old to support it.

In my git bisecting I find that the git tag cfitsio-4.4.0 in the upstream repo does not support out-of-tree builds, but cfitsio-4.4.0 does[^1]. I think if we switch to using (at least) cfitsio 4.5.0 and call insource(true) in the build script then that should solve your out-of-tree build problem. How do you feel about this?

If you continue to feel strongly we can provide an option to support cmake for the build process, in which case this PR will come in handy.

[^1]: during my git bisect I found the actual commit that first supports out-of-tree builds for the cfitsio repo is https://github.com/HEASARC/cfitsio/commit/d575c988095ac644f3877d2afc2b45d322e57522 which is in between 4.4.1 and 4.5.0.

simonrw avatar Mar 28 '25 23:03 simonrw

Is it possiable to support MSVC native compile on Windows platform? Compared with autotools, CMake is cross platfrom supported includes native MSVC.

@HaoxuanGuo rust-fitsio does not support MSVC at the moment, at least based on my testing. I do not remember why at this stage, but perhaps it was just that I could not compile cfitsio well enough. If you give @zec's suggestion (using CMAKE_GENERATOR) a try, can you let me know if you are successful?

simonrw avatar Mar 28 '25 23:03 simonrw

In my git bisecting I find that the git tag cfitsio-4.4.0 in the upstream repo does not support out-of-tree builds, but cfitsio-4.4.0 does1. I think if we switch to using (at least) cfitsio 4.5.0 and call insource(true) in the build script then that should solve your out-of-tree build problem. How do you feel about this?

I'll try that out, hopefully in the next couple of days, and get back to you... though I believe you'd actually want .insource(false).

If you continue to feel strongly we can provide an option to support cmake for the build process, in which case this PR will come in handy.

For my group's purposes, I am not wedded to the use of CMake, provided CFITSIO can be built out-of-tree by other means in a sufficiently-flexible manner (our cross-compilation setup's a little weird, and it took some effort to support it in the autotools-based build at all). I can definitely see how a CMake-based build might be nice for others as an option, though, and I can re-jigger the build script accordingly.

zec avatar Mar 31 '25 16:03 zec

@simonrw Sorry for the late reply. I tested compile cfitsio on Windows, it successed but with a dependency hell. cftisio depends on pthreads and zlib; zlib depends on pwsh. Which means rust-cfitsio is hard to build on a pure Windows without tuning. On another hand, it is not hard to install cfitsio from source for a user who has installed pthreads, zlib and pwsh. I whink it is not fluent on Windows with --features fitsio-src unless we would deal with these dependences. But, is it elegant to deal with these dependences on fitsio-src?

GuoHaoxuan avatar Apr 19 '25 18:04 GuoHaoxuan

@HaoxuanGuo thanks for posting this information, but I'd like to split up integrating cmake and getting MSVC support working into two separate issues. I already have an open issue for MSVC support however it's not very well fleshed out! Would you mind adding your thoughts over there?

Regarding cmake support @zec I think I am ok with including optional cmake support since it supports your use case. I don't think it should be default though, but I am unclear on the UX.

Cargo features are meant to be additive, however we have two opposing features:

  1. building cfitsio from source with autotools
  2. building cfitsio from source with cmake They are not additive, which I am ok with but we should probably proceed down one of two paths. Either
  3. we make three features: fitsio-src, autotools and cmake and raise a build error if an invalid combination is passed (e.g. fitsio-src alone, or both autotools and cmake)
  4. we use two features: cfitsio-src-autotools and cfitsio-src-cmake which uniquely select one of the two distinct combinations, but they are pretty ugly names.

I am siding with 1. here, so can we do the following:

  1. move the autotools integration behind an autotools feature flag and make the dependency optional
  2. put the changes you have made here behind a cmake feature flag
  3. add validation in the build.rs if an invalid combination is given, with a helpful error message

I am happy to help push this over the line but unfortunately I don't have much time to devote to this implementation myself, sorry.

simonrw avatar Apr 22 '25 08:04 simonrw

Regarding crate features: for optionally using the CMake build, I was thinking of having features with the following semantics:

  • fitsio-src: "build and link CFITSIO from source"
  • src-cmake (or cmake, or whatever name): "if and when we build C code, use CMake (instead of the implicit (and historical) default of Autotools)"

This would be backward compatible while still having sensible meanings for any combination of features [1].

(Apologies for not getting around to testing building with the new version of CFITSIO yet; I've gotten pulled over to other things at work for the time being.)

[1] -fitsio-src, +src-cmake would have the same effect as -fitsio-src, -src-cmake, but that's OK.

zec avatar Apr 22 '25 17:04 zec

I'm agree with @zec . Compatible is important for users and we should let it transparent.

MSVC support is another tough work, only cmake discuss here, nor MSVC would deal with later in another issue.

GuoHaoxuan avatar Apr 23 '25 05:04 GuoHaoxuan

Hi, sorry for the lack of responses. I am happy to include this feature with the fetaure flags you suggest, however I am unable to build this branch myself in its current state.

I get the following error:

    Updating crates.io index
  Downloaded pkg-config v0.3.31
  Downloaded cc v1.2.6
  Downloaded 2 crates (118.0KiB) in 0.76s
   Compiling cc v1.2.6
   Compiling pkg-config v0.3.31
   Compiling cmake v0.1.54
   Compiling fitsio-sys v0.5.5 (/Users/simon/dev/rust-fitsio/fitsio-sys)
error: failed to run custom build command for `fitsio-sys v0.5.5 (/Users/simon/dev/rust-fitsio/fitsio-sys)`

Caused by:
  process didn't exit successfully: `/Users/simon/.cargo-target/debug/build/fitsio-sys-bc2e23a7a5220328/build-script-build` (exit status: 101)
  --- stdout
  CMAKE_TOOLCHAIN_FILE_aarch64-apple-darwin = None
  CMAKE_TOOLCHAIN_FILE_aarch64_apple_darwin = None
  HOST_CMAKE_TOOLCHAIN_FILE = None
  CMAKE_TOOLCHAIN_FILE = None
  CMAKE_GENERATOR_aarch64-apple-darwin = None
  CMAKE_GENERATOR_aarch64_apple_darwin = None
  HOST_CMAKE_GENERATOR = None
  CMAKE_GENERATOR = None
  CMAKE_PREFIX_PATH_aarch64-apple-darwin = None
  CMAKE_PREFIX_PATH_aarch64_apple_darwin = None
  HOST_CMAKE_PREFIX_PATH = None
  CMAKE_PREFIX_PATH = None
  CMAKE_aarch64-apple-darwin = None
  CMAKE_aarch64_apple_darwin = None
  HOST_CMAKE = None
  CMAKE = None
  running: cd "/Users/simon/.cargo-target/debug/build/fitsio-sys-28c4f9abbc9ceb30/out/build" && CMAKE_PREFIX_PATH="" LC_ALL="C" "cmake" "/Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio" "-DCMAKE_OSX_ARCHITECTURES=arm64" "-DUseCurl=OFF" "-DBUILD_SHARED_LIBS=OFF" "-DUSE_PTHREADS=ON" "-DCMAKE_INSTALL_PREFIX=/Users/simon/.cargo-target/debug/build/fitsio-sys-28c4f9abbc9ceb30/out" "-DCMAKE_C_FLAGS= -O0 -fPIE -ffunction-sections -fdata-sections -fPIC --target=arm64-apple-macosx15.5" "-DCMAKE_C_COMPILER=/usr/bin/cc" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=arm64-apple-macosx15.5" "-DCMAKE_CXX_COMPILER=/usr/bin/c++" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=arm64-apple-macosx15.5" "-DCMAKE_ASM_COMPILER=/usr/bin/cc" "-DCMAKE_BUILD_TYPE=Debug"
  -- The C compiler identification is AppleClang 17.0.0.17000013
  -- The CXX compiler identification is AppleClang 17.0.0.17000013
  -- Detecting C compiler ABI info
  -- Detecting C compiler ABI info - done
  -- Check for working C compiler: /usr/bin/cc - skipped
  -- Detecting C compile features
  -- Detecting C compile features - done
  -- Detecting CXX compiler ABI info
  -- Detecting CXX compiler ABI info - done
  -- Check for working CXX compiler: /usr/bin/c++ - skipped
  -- Detecting CXX compile features
  -- Detecting CXX compile features - done
  -- Found Pthreads: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/lib/libpthread.tbd
  -- Looking for gethostbyname
  -- Looking for gethostbyname - found
  -- Looking for connect
  -- Looking for connect - found
  -- Configuring done (2.0s)
  -- Generating done (0.0s)
  -- Build files have been written to: /Users/simon/.cargo-target/debug/build/fitsio-sys-28c4f9abbc9ceb30/out/build
  running: cd "/Users/simon/.cargo-target/debug/build/fitsio-sys-28c4f9abbc9ceb30/out/build" && LC_ALL="C" "cmake" "--build" "/Users/simon/.cargo-target/debug/build/fitsio-sys-28c4f9abbc9ceb30/out/build" "--target" "install" "--config" "Debug" "--parallel" "8"
  [  1%] Building C object CMakeFiles/cfitsio.dir/buffers.c.o
  [  2%] Building C object CMakeFiles/cfitsio.dir/drvrnet.c.o
  [  4%] Building C object CMakeFiles/cfitsio.dir/checksum.c.o
  [  5%] Building C object CMakeFiles/cfitsio.dir/editcol.c.o
  [  6%] Building C object CMakeFiles/cfitsio.dir/drvrfile.c.o
  [  8%] Building C object CMakeFiles/cfitsio.dir/cfileio.c.o
  [  9%] Building C object CMakeFiles/cfitsio.dir/drvrmem.c.o
  [ 10%] Building C object CMakeFiles/cfitsio.dir/edithdu.c.o
  [ 12%] Building C object CMakeFiles/cfitsio.dir/eval_f.c.o
  [ 13%] Building C object CMakeFiles/cfitsio.dir/eval_l.c.o
  [ 14%] Building C object CMakeFiles/cfitsio.dir/eval_y.c.o
  [ 16%] Building C object CMakeFiles/cfitsio.dir/f77_wrap2.c.o
  [ 17%] Building C object CMakeFiles/cfitsio.dir/f77_wrap1.c.o

  --- stderr
  CMake Warning (dev) at CMakeLists.txt:6 (PROJECT):
    cmake_minimum_required() should be called prior to this top-level project()
    call.  Please see the cmake-commands(7) manual for usage documentation of
    both commands.
  This warning is for project developers.  Use -Wno-dev to suppress it.

  CMake Deprecation Warning at CMakeLists.txt:7 (CMAKE_MINIMUM_REQUIRED):
    Compatibility with CMake < 3.10 will be removed from a future version of
    CMake.

    Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
    to tell CMake that the project requires at least <min> but has been updated
    to work with policies introduced by <max> or earlier.


  CMake Warning:
    Manually-specified variables were not used by the project:

      CMAKE_ASM_COMPILER
      CMAKE_ASM_FLAGS


  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/editcol.c:129:46: warning: absolute value function 'abs' given an argument of type 'long' but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
    129 |     newsize = (newsize + pcount) * gcount * (abs(longbitpix) / 8);
        |                                              ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:323:7: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    323 |       alarm(0);
        |       ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:356:5: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    356 |     alarm(net_timeout*10);
        |     ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:374:5: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    374 |     alarm(net_timeout);
        |     ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/editcol.c:129:46: note: use function 'labs' instead
    129 |     newsize = (newsize + pcount) * gcount * (abs(longbitpix) / 8);
        |                                              ^~~
        |                                              labs
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:390:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    390 |   alarm(0);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:456:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    456 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:615:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    615 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:823:5: error: call to undeclared function 'close'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    823 |     close(sock);
        |     ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1060:5: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1060 |     alarm(0);
        |     ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1071:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1071 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1095:10: warning: format specifies type 'unsigned int' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat]
   1094 |      snprintf(errStr,MAXLEN,"Content-Length not a multiple of 2880 (https_open) %u",
        |                                                                                 ~~
        |                                                                                 %zu
   1095 |          inmem.size);
        |          ^~~~~~~~~~
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/secure/_stdio.h:60:62: note: expanded from macro 'snprintf'
     60 |   __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
        |                                                              ^~~~~~~~~~~
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1138:6: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1138 |      alarm(0);
        |      ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1148:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1148 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1182:6: warning: format specifies type 'int' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat]
   1181 |             "Content-Length not a multiple of 2880 (https_file_open) %d",
        |                                                                      ~~
        |                                                                      %zu
   1182 |             inmem.size);
        |             ^~~~~~~~~~
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/secure/_stdio.h:60:62: note: expanded from macro 'snprintf'
     60 |   __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
        |                                                              ^~~~~~~~~~~
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1347:5: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1347 |     alarm(0);
        |     ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1358:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1358 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1419:13: warning: format specifies type 'unsigned int' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat]
   1418 |         snprintf(errStr,MAXLEN,"Content-Length not a multiple of 2880 (ftps_open) %u",
        |                                                                                   ~~
        |                                                                                   %zu
   1419 |             inmem.size);
        |             ^~~~~~~~~~
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/secure/_stdio.h:60:62: note: expanded from macro 'snprintf'
     60 |   __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
        |                                                              ^~~~~~~~~~~
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1467:6: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1467 |      alarm(0);
        |      ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1477:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1477 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1571:9: warning: format specifies type 'int' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat]
   1570 |                "Content-Length not a multiple of 2880 (ftps_file_open) %d",
        |                                                                        ~~
        |                                                                        %zu
   1571 |                inmem.size);
        |                ^~~~~~~~~~
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/secure/_stdio.h:60:62: note: expanded from macro 'snprintf'
     60 |   __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
        |                                                              ^~~~~~~~~~~
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1622:6: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1622 |      alarm(0);
        |      ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:1632:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   1632 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:2116:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   2116 |   alarm(net_timeout);
        |   ^
  /Users/simon/dev/rust-fitsio/fitsio-sys/ext/cfitsio/drvrnet.c:2253:3: error: call to undeclared function 'alarm'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   2253 |   alarm(net_timeout);
        |   ^
  fatal error: too many errors emitted, stopping now [-ferror-limit=]
  4 warnings and 20 errors generated.
  gmake[2]: *** [CMakeFiles/cfitsio.dir/build.make:149: CMakeFiles/cfitsio.dir/drvrnet.c.o] Error 1
  gmake[2]: *** Waiting for unfinished jobs....
  1 warning generated.
  eval.y:5022:16: warning: expression result unused [-Wunused-value]
   5022 |                  this->value.undef;  /* Dummy - BITSTRs do not have undefs */
        |                  ~~~~~~~~~~~ ^~~~~
  eval.y:5116:16: warning: expression result unused [-Wunused-value]
   5116 |                  this->value.undef;  /* Dummy - BITSTRs do not have undefs */
        |                  ~~~~~~~~~~~ ^~~~~
  2 warnings generated.
  gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/cfitsio.dir/all] Error 2
  gmake: *** [Makefile:136: all] Error 2

  thread 'main' panicked at /Users/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cmake-0.1.54/src/lib.rs:1119:5:

  command did not execute successfully, got: exit status: 2

  build script failed, must exit now
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

$

It might be a macOS aarch64 issue, however this is my primary development platform and therefore it is the highest priority for me. We regularly test Linux on CI anyway.

I don't know if you are using macOS yourself, however if you are not I'm happy to dive more into this failure myself. It just might take a while.

In the meantime you are able to build your feature branch for yourself, and include it into your projects. I hope that's enough to enable this workflow for you at least, and you are not blocked by this.

simonrw avatar Jun 29 '25 08:06 simonrw

I have (finally) gotten around to updating this pull request... in large part because multiple teammates ran into the same compiler errors on macOS as @simonrw.

This rev of the pull request provides a choice between Autotools and CMake when using fitsio-src, as previously proposed. The CMake build now works on macOS and MSYS2.

zec avatar Oct 22 '25 19:10 zec

@zec it is now available in fitsio version 0.21.9

simonrw avatar Oct 22 '25 23:10 simonrw