Skip to content
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

Add CI for Windows #82

Closed
wants to merge 5 commits into from
Closed

Conversation

Flamefire
Copy link
Contributor

As some Windows code might be different it is worth testing. Easiest solution would be to add

os: 
  - linux
  - windows

to travis.yml, but I dind't want to build all configurations.

Note: Dependencies are a PITA on Windows. Hence I didn't install FFTW or libsndfile, although I tried at least for FFTW but failed. Possible solution: Use vcpkg and CMAKE_TOOLCHAIN_FILE or try Mingw for building and download and copy prebuild binaries. The former requires compilation of FFTW (slow), the latter knowledge where binaries will be placed on builds to copy DLLs to). So not great either.

CMakeLists.txt Outdated
@@ -10,6 +10,7 @@ endif()
option(LIBSAMPLERATE_TESTS "Enable to generate test targets" ${IS_ROOT_PROJECT})
option(LIBSAMPLERATE_EXAMPLES "Enable to generate examples" ${IS_ROOT_PROJECT})
option(LIBSAMPLERATE_INSTALL "Enable to add install directives" ${IS_ROOT_PROJECT})
option(LIBSAMPLERATE_ENABLE_WARNINGS "Enable compiler warnings and fail compile if any triggers" OFF)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think disabling warnings by default is a bad idea. I agree they should never be promoted to errors by default, but all warnings should be visible.

Even if warnings were enabled by default I would question the wisdom of being able to disable them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I propose 2 options: LIBSAMPLERATE_ENABLE_WARNINGS, LIBSAMPLERATE_ENABLE_WERROR. Alternatively just the latter.

Reason for having an option with default OFF is that I set those as INTERFACE option which enables them on all targets linking to this. If I remove LIBSAMPLERATE_ENABLE_WARNINGS and just add LIBSAMPLERATE_ENABLE_WERROR then I'd add warnings per target (PRIVATE for samplerate, tests and examples can be PUBLIC, much easier with #69 as there is a common library used by all tests/examples respectively, so only repeat them 3 times)

BTW: There are some warnings (especially on Windows) about float->double conversions which I disabled here. Better would be to declare constants with f suffix and add explicit casts to out[k] = ... assignments which also makes the conversion visible and is good IMO, but you said you want to avoid casts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having LIBSAMPLERATE_ENABLE_WERROR would mirror the autotool config option --enable-werrror.

There are some warnings (especially on Windows) about float->double conversions

I think there is a MSVC #pragma to disable those.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So drop LIBSAMPLERATE_ENABLE_WARNINGS and add LIBSAMPLERATE_ENABLE_WERROR?

I think there is a MSVC #pragma to disable those.

So add #pragma push/disable/pop to the code instead of conversions? I'd advice against that but your call

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, enable warnings by default, enable -Werror as an option.

Yes, I would prefer the #prama fix than adding casts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. As warnings are now always enabled I check that the compiler does not error out if the flag is passed (check_c_compiler_flag)

Also done. Used the MSVC definition to only add them for MSVC to avoid e.g. -Wunknown-pragma warnings. I'm not particularly fond of suppressing the warnings as IMO narrowing conversions shouldn't be done implicitly as loss of data happens.

@@ -31,4 +31,4 @@ script:
- cd build
- cmake -DBUILD_SHARED_LIBS=$CMAKE_SHARED -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_C_FLAGS="-Wall -Wextra -Werror" ..
- cat config.h
- make && make test
- cmake --build . --config $BUILD_TYPE && ctest --output-on-failure -C $BUILD_TYPE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That disables the autotool build in favor of the CMake build. Not a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The autotool build is still done but in a completely different job: https:/erikd/libsamplerate/pull/82/files#diff-354f30a63fb0907d4ad57269548329e3R16

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, the way this travis file looks now, it seems like CMake is the default, when it is not. Autotools is the default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First: Why? Isn't CMake superior to autotools? It can generate buildsystems on any OS.

In this case it kinda has to be this way: All paths (windows, linux, optimized, non-optimized) go to the "default" script tag so the code there has to be the os-agnostic, generic code. Doing it differently in an attempt to make the autotools job more prominent would obfuscate the code (e.g. use yaml anchors)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't CMake superior to autotools?

No, I don't think so and I know I am not alone.

I have used Autotools for 20 years. Its not perfect, but I understand it and know how to use it. I don't know CMake anywhere near as well, and from what I have seen of it, I do not think it is as good as Autotools.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally like CMake more, especially if i look at what is required for autotools: https:/erikd/libsamplerate/blob/master/Makefile.am, https:/erikd/libsamplerate/blob/master/autogen.sh, https:/erikd/libsamplerate/blob/master/configure.ac compared to CMake https:/erikd/libsamplerate/blob/master/CMakeLists.txt.

But I don't want to start a philosophic discussing about meta-buildsystems. So only the advantages of CMake in this case:

  • Generating build systems for windows (e.g. MSVC projects)
  • Use of the library as a git submodule without the need to install it from a CMake project via add_subdirectory. This also greatly reduces the pain of using this on Windows/cross-platform projects with all the dependencies on compilers, options, ...

But here all this seems to be void. Why talk about a "default"? Both work are thoroughly tested and a user can choose which one he wants/needs (if he isn't on windows in which case there is no choice)

src/src_sinc.c Outdated
@@ -31,9 +31,20 @@
typedef int32_t increment_t ;
typedef float coeff_t ;

#ifdef _MSC_VER
#define MSVC_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be done in CMake somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that would be more work for no gain. MSVC guarantees that _MSC_VER is defined

Work: Add configured define to config.h if compiling with MSVC
Gain: Can use #if SRC_MSVC instead of the #ifdef _MSC_VER where the former would error on compile time if it is not set catching e.g. a typo in _MSC_VER

But: If _MSC_VER was mistyped then the warnings won't be disabled and hence CI would fail due to the warnings thrown. Therefore a mistyped macro name would already result in a compile-time error which is what is the goal of using #if over #ifdef, but using _MSC_VER is less work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would vastly prefer to limit compiler specific specical case handling creeping in the code and if it does creep into the code it should be mininal. This approach does not meet those goals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, I could completely disable this warning in CMake if this is what you meant. I had done that initially: b487324#diff-af3b638bc2a3e6c650974192a53c7291R113
But earlier you said to use the pragma instead: #82 (comment)

My preferred approach would be to use the proper explicit casts and f suffix for float constants. This makes the truncation obvious which might be important knowledge when changing the code. This would also never required warning suppressions on any compiler

Copy link
Contributor Author

@Flamefire Flamefire Aug 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added another commit which does just that: Explicit casts where truncation happens. This makes the compilers happy so no suppression required. 37473c2

Just choose which one you want:

  1. warning suppression flag added in CMake
  2. pragma based suppression
  3. explicit handling of narrowing conversions (my preference)

Notes:

  • It might be worth checking if some of those calculations should really be done using double instead of float.
  • Loops are used instead of manual unrolling. The compiler is at least as good and in this case generates the same machine code with less code and room for error: https://godbolt.org/z/4a27qn
  • To kinda prove the above: The manually unrolled loops in calc_output_multi are suboptimal due to incorrect tail handling: The switch (ch % 8) has to be place on top of the do otherwise the condition and conditional jump will be executed on every iteration instead of once. I'd suggest to just use a loop and let the compiler decide.

Edit: The compiler-optimized loop is actually faster: http://quick-bench.com/znRud0mQhKSWDhgJns_5eYP8_wk

@@ -21,2469 +21,2469 @@ static const struct fastest_coeffs_s
} fastest_coeffs =
{ 128,
{
8.31472372954840555082e-01,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing these really should not be necessary. These are three large tables that take half as much room as float as they would as double. Memory space is cheap nowadays, but it almost certainly is worth minimizing memory to CPU bandwidth.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand exactly. This is a float array (coeff_t coeffs [2464] ; with coeff_t == float)

My only change here is to make the truncation from double to float explicit because the compiler (rightfully) complained that this might be accidental.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

complained that this might be accidental.

Its not accidental. The compiler should be informed in a way that doesn't change nearly every line in the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a line is like floatVar = doubleValue which does look accidental then why isn't the correct change floatVar = floatValue? And if the whole file consists of such lines then you gotta change the whole file. Nothing wrong with that especially as it can be done with Search&Replace.

The other solution is a suppression via compiler specific pragmas but you objected them in #82 (comment). In the end it doesn't matter which way it is done: Either by passing float values to float variables or by passing double values to float variables and surrounding the region with a pragma saying "don't tell me about truncating conversions". Just needs a decision. See #82 (comment)

@Flamefire
Copy link
Contributor Author

Rebased to current master. What is the state of this? Having CI for windows and with Werror is valuable.

Questions/answers asked previously:

  • autotools: still available as before, tested on CI, no change in this PR
  • truncation warnings for implicit double -> float on e.g. MSVC:
    • 3 options provided: suppress globally, suppress locally or use proper constants and conversions
    • First 2 implemented for MSVC only, last works on all compilers and is the more correct/robust solution
    • see Add CI for Windows #82 (comment) and following
    • last is the current option (last commit)

Use the cmake and ctest commands with explicit build type so they work
with other generators like MSVC solutions
Useful for (and used in) CI
Add some defines required to fix MSVC warnings about "deprecated" CRT functions
@evpobr
Copy link
Member

evpobr commented Oct 20, 2020

I think we need to use GitHub Actions instead of Travis CI.

@Flamefire
Copy link
Contributor Author

Why? I mean: This PR shows that travis is possible. Having said that I also like GHA due to nicer syntax although I haven't used the windows runners yet.

@evpobr evpobr self-assigned this Dec 3, 2020
@evpobr
Copy link
Member

evpobr commented Dec 3, 2020

GitHub actions intergated with Windows CI tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants