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 CMake build system (based on previous work from @mdsitton and @jcelerier) and CI #24

Merged
merged 1 commit into from
Feb 3, 2018

Conversation

Bobo1239
Copy link
Contributor

@Bobo1239 Bobo1239 commented Nov 26, 2017

Hi @erikd,
thanks for creating this library. I wanted to create some Rust bindings and to simplify cross-platform compilation I continued the previous CMake attempts from @mdsitton and @jcelerier. I've also tried to setup some CI (Travis for Linux; Appveyor for Windows). Admittedly I've not really done much C development till now so please feel free to point out any problems with this PR.

https://travis-ci.org/Bobo1239/libsamplerate
https://ci.appveyor.com/project/Bobo1239/libsamplerate

@erikd
Copy link
Member

erikd commented Nov 28, 2017

This is a pretty large PR. Probably won't get time to have a proper look at it until the weekend.

@jcelerier
Copy link

hey, sorry, I had entirely forgot my PR. this looks pretty nice and complete ! But are you sure you want to support CMake versions that didn't even have PUBLIC / PRIVATE ? Are there still widely-used systems with such old version (that couldn't just install CMake's statically-built latest version) ?

@Bobo1239
Copy link
Contributor Author

Bobo1239 commented Nov 28, 2017

@erikd No worries, take your time. :)
@jcelerier Tbh I was just trying to get everything here to become green (as they are now) and some of those platforms (they are Docker images) have CMake 2.8. I figured we aren't really using any new CMake features so it wouldn't hurt to support an older verson. But as I said in my opening post I don't have an overview over this ecosystem so you guys have to make the call whether it's worth it to support old CMake versions.

@erikd
Copy link
Member

erikd commented Nov 28, 2017

libsndfile builds on travis with CMake min version of 3.1.3. Maybe figure out what that is doing.

@Bobo1239
Copy link
Contributor Author

Those builds aren't normal Travis instances; they are cross compiling and testing on many different Docker images (some of them using qemu internally?) and aren't maintained by me. (They are from cross which is ""Zero setup" cross compilation and "cross testing" of Rust crates"). If you guys don't think it's worth supporting such an old CMake version I have no problems reverting the last few changes. I would then just drop those few Travis instances or try to upgrade CMake in those Docker images.

@erikd
Copy link
Member

erikd commented Nov 29, 2017

Yeah, I don't think its worth supporting any CMake version older than the ones libsndfile uses.

@jcelerier
Copy link

that's interesting: these docker images have rust which is very recent, but don't have five-years old versions of CMake :p are they hosted somewhere on github ? it could be worth it to send PRs to them so that everyone doing such a work can at least leverage recent versions.

@Bobo1239
Copy link
Contributor Author

Bobo1239 commented Nov 29, 2017

Reverted the last changes.
The docker images are here. They are using different Ubuntu base images (ranging from 12.04 to 16.04) because of cross-rs/cross#85. (Basically they're using the oldest possible glibc to maximize support for the produced binaries.)
edit: I'll just update CMake on those Docker images. There's already a script to install a specific CMake version which is already used in some images and most of them are based on Ubuntu 16.04 (CMake 3.5.1) anyways.

@tresf
Copy link

tresf commented Dec 15, 2017

@Bobo1239 do you offer any build artifacts for libsamplerate? If not, would the project entertain an automatic upload (e.g. github releases, etc) to complement the cmake support?

I'm most interested in the win32 artifacts for multi-platform. The other OSs (unix/linux/macos) have methods to fetch libsamplerate. CMake drastically simplifies the MSVC++ setup and I'd like to add the 32-bit and 64-bit artifacts (plus headers) into the scoop.sh package manager.

CMakeLists.txt Outdated
set(HAVE_ALSA ${ALSA_FOUND})

find_package(Sndfile)
set(HAVE_SNDFILE ${SNDFILE_FOUND})
Copy link

Choose a reason for hiding this comment

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

@Bobo1239 cmake does not seem to provide FindSndfile.cmake or FindFFTW.cmake on some systems which means if they're in a non-standard location, the linking and including won't work as it would in a vanilla POSIX environment.

Would you consider adding an additional pkg-config dependency on this? Then you could do the following:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 394de75..1b85d17 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,7 @@ include(CheckIncludeFiles)
 include(CheckSymbolExists)
 include(CheckTypeSize)
 include(ClipMode)
+include(FindPkgConfig)

 set(SAMPLERATE_SRC
        ${PROJECT_SOURCE_DIR}/src/samplerate.c
@@ -53,12 +54,24 @@ clip_mode()

 find_package(ALSA)
 set(HAVE_ALSA ${ALSA_FOUND})
+if(ALSA_FOUND)
+       include_directories("${ALSA_INCLUDE_DIRS}")
+       link_directories("${ALSA_LIBRARY_DIRS}")
+endif()

-find_package(Sndfile)
+pkg_check_modules(Sndfile sndfile>=1.0.0)
 set(HAVE_SNDFILE ${SNDFILE_FOUND})
+if(SNDFILE_FOUND)
+       include_directories("${SNDFILE_INCLUDE_DIRS}")
+       link_directories("${SNDFILE_LIBRARY_DIRS}")
+endif()

-find_package(FFTW)
+pkg_check_modules(FFTW3 fftw3>=3.0.0)
 set(HAVE_FFTW3 ${FFTW_FOUND})
+if(FFTW3_FOUND)
+       include_directories("${FFTW3_INCLUDE_DIRS}")
+       link_directories("${FFTW3_LIBRARY_DIRS}")
+endif()

 configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FindSndfile.cmake and FindFFTW.cmake are the cmake directory which should be loaded by set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake) at the top. (ClipMode.cmake is also affected by this.)

Regarding pkg-config: What do @erikd and @jcelerier think? Should I switch from the two cmake modules to pkg-config? I really don't know what is better supported across the board.

Copy link

@tresf tresf Dec 15, 2017

Choose a reason for hiding this comment

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

I really don't know what is better supported across the board.

To give a bit more background information on this:

Ubuntu 14.04, default for Travis-CI:

locate -i FindALSA.cmake
(found) /usr/share/cmake-3.5/Modules/FindALSA.cmake
locate -i FindFFTW
(not found)
locate -i FindSndfile
(not found)

What this means is if a project requires any of the variables expected to be available for includes or libraries, they won't be available. Msys2 re-uses the POSIX-style paths so it hides this bug as the default include and lib paths work out of the box.

In the case of a build system that has CMAKE_PREFIX_PATH setup to search for these libraries, it'll find that they exist, but not know how to find the headers or the libraries without the appropriate .cmake file if they're installed anywhere except where a Unix environment would expect.

Case and point is that if you were to download the libsndfile from the website, it offers a libsndfile.pc file, not a FindSndfile.cmake file.

Copy link

@tresf tresf Dec 15, 2017

Choose a reason for hiding this comment

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

@Bobo1239 On second thought, perhaps this is a problem with my environment. CMAKE_PREFIX_PATH clearly states that it searches the same paths as pkg-config. Here's an excerpt from the website:

[CMAKE_PREFIX_PATH] contains the “base” directories, the FIND_XXX() commands append appropriate subdirectories to the base directories. So FIND_PROGRAM() adds /bin to each of the directories in the path, FIND_LIBRARY() appends /lib to each of the directories, and FIND_PATH() and FIND_FILE() append /include .

I will investigate this some more on my end as to why the paths are found, but the includes and libs are not. If working properly, the existing code should work just fine with cmake.

Copy link
Contributor Author

@Bobo1239 Bobo1239 Dec 15, 2017

Choose a reason for hiding this comment

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

I think you may have misunderstood me. FindFFTW and FindSndFile are distributed with the source (in the cmake directory) in the repo and aren't required from the environment. And they should get loaded because we're extending CMAKE_MODULE_PATH to include the cmake directory.
edit: Didn't see your response before I submitted this.

Copy link

@tresf tresf Dec 15, 2017

Choose a reason for hiding this comment

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

@Bobo1239 you are correct, I missed that they were distributed with the project. I think I found the culprit: https://github.com/erikd/libsamplerate/pull/24/files#r157310099. Your original technique should be just fine but I recommend making the variables consistently named. Also, include_directories(...) and link_directories(...) will still be required for some environments. That part will still need to be (fixed to use the right variables and) added as a safeguard, even if redundant on some systems.

Copy link

@tresf tresf Dec 16, 2017

Choose a reason for hiding this comment

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

I looked at some more FindXXX.cmake modules and they all appear to follow slightly different conventions, so it's hard to argue for consistency. Working with what we have now... Here's what works out of the box using this PR without adding pkg-config:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 394de75..a2aad7f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,11 +53,23 @@ clip_mode()

 find_package(ALSA)
 set(HAVE_ALSA ${ALSA_FOUND})
+if(ALSA_FOUND)
+  include_directories("${ALSA_INCLUDE_DIR}")
+  link_directories("${ALSA_LIBRARY}/../")
+endif()

 find_package(Sndfile)
 set(HAVE_SNDFILE ${SNDFILE_FOUND})
+if(SNDFILE_FOUND)
+  include_directories("${SNDFILE_INCLUDE_DIR}")
+  link_directories("${SNDFILE_LIBRARY}/../")
+endif()

 find_package(FFTW)
+if(FFTW_FOUND)
+  include_directories("${FFTW_INCLUDES}")
+  link_directories("${FFTW_LIBRARIES}/../")
+endif()
 set(HAVE_FFTW3 ${FFTW_FOUND})

 configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)

@Bobo1239
Copy link
Contributor Author

@tresf I'll try to look into AppVeyor build artifacts this weekend.

@@ -0,0 +1,25 @@
# From: https://github.com/wjakob/layerlab/blob/master/cmake/FindFFTW.cmake
# FIXME: License concerns?
Copy link

@tresf tresf Dec 15, 2017

Choose a reason for hiding this comment

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

The license is BSD 2-clause "Simplified" License. (found it at layerlab) This and the BSD 3-clause are GPL compatible and very common for cmake scripts.

Copy link
Member

Choose a reason for hiding this comment

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

I'd be fine with either a BSD or BSD 2-clause license for the CMake files.

set (FFTW_FIND_QUIETLY TRUE)
endif (FFTW_INCLUDES)

find_path (FFTW_INCLUDES fftw3.h)
Copy link

@tresf tresf Dec 15, 2017

Choose a reason for hiding this comment

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

Ok... I think I found the problem. I had expected this to be FFTW_INCLUDE_DIRS and FFTW_LIBRARY_DIRS. See FindSndfile.cmake as an example Edit: No, that's slightly off as well. This is definitely why pkg-config worked and find_package failed. pkg-config uses more predictable names across the board; cmake you can provide your own. I can change my code to accommodate.

@tresf
Copy link

tresf commented Dec 16, 2017

@Bobo1239 good call on target_link_libraries. a1ba332 now fixes building on non-posix environments. Thanks!

@Bobo1239 Bobo1239 force-pushed the master branch 3 times, most recently from 36ab528 to 395e851 Compare December 17, 2017 05:05
@Bobo1239
Copy link
Contributor Author

@tresf Would this be enough for your use case?

@tresf
Copy link

tresf commented Dec 17, 2017

@Bobo1239 I will also be needing the header file and the pkg-config (.pc) file. libsndfile is a good example and here's how I've written the release into the scoop package manager.

Also, long-term, if there are no objections, it would be nice to have the file hosted at an unauthenticated, tagged location such as the github release area, if @erikd would entertain this. AppVeyor is able to do this.

@Bobo1239
Copy link
Contributor Author

@tresf I guess it would make sense to setup the install target in CMake so we get that kind of structure for all platforms (also we're currently not generating a .pc file at all I think?)
I don't know when I'll have the time to try that out. If you need it rather sooner than later we can maybe try to land this PR first and let somebody else do that?

@tresf
Copy link

tresf commented Dec 17, 2017

@Bobo1239 AFAIK .pc file should look like this:

prefix=
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: samplerate
Description: An audio Sample Rate Conversion library
Requires: 
Version: 0.1.8
Libs: -L${libdir} -lsamplerate
Libs.private: Ext/libsndfile.a
Cflags: -I${includedir} 

CMake can configure this file like so (sample, I haven't tested it for syntax errors)

SET(prefix "")
SET(exe_prefix "\\${prefix}")
SET(libdir "\\${exec_prefix}/lib")
SET(includedir "\\${prefix}/include")
SET(VERSION "${PROJECT_VERSION}")
SET(LIBS "Ext/libsndfile.a")
CONFIGURE_FILE(samplerate.pc.in samplerate.pc @ONLY)

@tresf
Copy link

tresf commented Dec 17, 2017

@tresf I guess it would make sense to setup the install target in CMake so we get that kind of structure for all platforms

I agree, although I can rearrange the files in the packaging utility if needed, that's what we have to do with fftw's for example. Getting the output files is enough to start offering this package to win32 developers.

@Bobo1239 Bobo1239 force-pushed the master branch 6 times, most recently from bf22644 to 2274269 Compare December 18, 2017 01:55
@Bobo1239
Copy link
Contributor Author

Bobo1239 commented Dec 18, 2017

@tresf tresf mentioned this pull request Dec 19, 2017
15 tasks
@tresf
Copy link

tresf commented Dec 19, 2017

@Bobo1239 Yes, it works quite well actually. :)

  -- Checking for module 'samplerate>=0.1.8'
+ --   Found samplerate, version 0.1.9

A working scoop.sh bucket is here.

@Bobo1239
Copy link
Contributor Author

Bobo1239 commented Jan 6, 2018

@erikd Is there anything I should do here?

if (file == NULL)
return name ;

#if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__)
Copy link
Member

Choose a reason for hiding this comment

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

Something's not right there. Why has that #if been removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem here is the pclose call afterwards which fails to link on Windows. An alternative would be to replace is_pipe with #define IS_PIPE (+ #undef IS_PIPE at the end) and

if (is_pipe)
	pclose (file) ;
else
	fclose (file) ;

with

#ifdef IS_PIPE
	pclose (file) ;
#else
	fclose (file) ;
#endif

Do you want me to do that?

Copy link
Member

Choose a reason for hiding this comment

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

What problem was this change trying to address?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Native Windows (MSVC) doesn't provide pclose (though apparently it has _pclose) so it must be removed by the preprocessor.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, how about you just sqash this PR down to a single commit and I'll sort it out,

@erikd
Copy link
Member

erikd commented Jan 6, 2018

Would you be fix the #if issue and then squash that down to a single commit crediting the other two contributors and giving a good overview commit message?

This commit adds a new CMake-based build system. The build time configuration
should match the one by autoconf.
Then this build system gets tested on Travis (Linux) and AppVeyor (Windows;
MSVC and MinGW). Additionally on AppVeyor, a build artifact is produced for
easier distribution to Windows.
Some minor changes are introduced to fix compilation on Windows.

This commit is based on previous attempts at a CMake-based build by
Jean-Michaël Celerier (jcelerier) and Matthew Sitton (mdsitton).
@Bobo1239
Copy link
Contributor Author

Sorry for the delay. Finally got around to do this. (Was busy with university...)
I'm not sure if this qualifies as a "good overview commit message" so tell if there's anything you wish me to add. Besides a rebase onto master I haven't done any changes to the code.
In case you're merging this: don't forget to enable AppVeyor for the repo (and PRs?).

@erikd erikd merged commit 73cb39b into libsndfile:master Feb 3, 2018
@erikd
Copy link
Member

erikd commented Feb 3, 2018

Thank you all for your contribution!

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.

4 participants