-
Notifications
You must be signed in to change notification settings - Fork 165
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 project #7
Conversation
Hi! Thanks a lot for this contribution! As you can tell from the other open pull request, this project is definitely in need of a good cross-platform build system. I think that CMake is probably the best candidate, and that your pull request is a good start. I'd like to work with you to tailor it to this project. I really appreciate your contribution back to this project, and I understand that I have little ground to critique work done by others in their own time. That said, I have some comments, which I will place in the code. It would be nice if you could have a look at them, but you are, of course, under no obligation. |
I appreciate your feedback and will work towards an implementation we are both comfortable with. That said this one of my CMake templates with some necessary modifications and it didn't get too much love, because I was in a hurry (i.e. no NEON support etc.). Please note that (as stated in the copyright notice) I'm not the author of the I think I'll answer the rest of your questions/address your comments in place. |
@aklomp can you estimate when you can answer my questions? I don't want to pressure you, but I'm currently planning my weekend and it would be nice if I can take this into account. |
No problem. I don't think I'll be doing much on the project today as I have other plans this evening, and the same is mostly true for tomorrow. (I might have some time to work on this project, but no guarantees.) On Sunday, I actually have to be in the office for a server migration, so I think it's a safe bet to say that I won't be doing much over the weekend. Also, I planned to "comment" in the form of pushing some example code, which takes a bit more time than just typing text. |
a41915c
to
03e7660
Compare
Status UpdateI reworked and simplified quite some bits. Currently all target platform / instruction set detection code is disabled (no third party code anymore 🎉). I included some SIMD instruction set detection code for SSSE3 and AVX2 and an infrastructure skeleton for it located in I did some research regarding NEON, but I need an ARM platform in order to check the cmake behavior on that platform and the implications for cross compiling, i.e. that won't be added before my Odroid-C1+ arrives... Did I forget something? Addendum: Just to clarify it: You can build the library for every platform and with every compiler cmake supports, but SSSE3 and AVX2 are only supported with the gcc, clang and msvc compilers... |
Add static library target. Add SIMD support on x86 platforms. Add install target. Make config.h optional, i.e. the HAVE_* definitions can be supplied via the commandline. Add test driver projects and makefile commands.
03e7660
to
e12e3cd
Compare
Just added cmake projects for the test driver and the benchmark. |
Looks good, I'll review it on short notice! Do you consider it fit to merge as-is? Don't worry about the NEON stuff, I have a Raspberry Pi 2B which has NEON32 extensions, and I can run NEON64 in an emulator. We can iterate. Sorry for all the delay btw. Your pull request has been on my radar for the whole time, but I've also been occupied with implementing a faster algorithm (currently in Master), and working on merging OpenMP support (see Issue #9). |
The scripts work well enough for the plain, SSSE3 and AVX2 use cases to be merged . And as you said we
Awesome work! 👍 |
Just checked out some of your CMake stuff. I'm definitely new at this, but I'm open to learn. I wanted to build the benchmarks with AVX2 support, so I tried this: cmake -DBASE64_WITH_AVX2=1 .
make
cd test
cmake .
make This series of commands fails for me. It looks like the generated Makefiles in Other things I noticed: the |
FWIW, I managed to compile the tests by adding the following to find_library(LIBBASE64 libbase64.a ..)
target_link_libraries(${TEST_NAME} ${LIBBASE64}) |
Well, try this (after you completely cleaned the project dir): cd /path/to/project/src
mkdir build
cd build
cmake -DBASE64_WITH_AVX2=1 ..
make
make test Explanation
Furthermore cmake likes hierarchies, so One more thing to note: |
@aklomp are you still interested in this? If yes I will invest some time updating the build files soon:tm:. |
Sorry about the silence, I didn't intend to string you along. I am definitely still interested in
Maybe this is how we can proceed:
|
I don't like cmake either, but sadly as you said it's a de-facto standard and just works:tm: :smile:
👍
Yeah, I would like to get this into the upstream project, but I think we should wait with merging until you can maintain the build files yourself. Instead I will watch your repository and keep the cmake files in my fork in sync with the upstream repository. I suggest you add a link in the project description referring to the fork; this way I don't have to open new pull requests every time something changes and people can use the cmake tooling now, so:
Are you 🆗 with this? |
Sync code with upstream in order to update the cmake build files.
b361414
to
0d952ae
Compare
0d952ae
to
796a5a8
Compare
Include msvc fixes recently pushed to master.
Adapt the build system to the recent source code changes. Add platform detection code for arm, arm64, x86 and x64. Offer SIMD compile options depending on platform. Add preliminary support for NEON codecs. Enable the SIMD compile options by default. - Clean cmake scripts. - Bump version to 0.3.0. - Fix UTF-8 issues.
0d41483
to
8a11f92
Compare
Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
Hi everyone. What's the plan to get cmake support merged? It looks like the latest feedback has been taken into account, and having some support would be nice. It will be easier to iterate on cmake support as the community starts to use it. |
CMakeLists.txt
Outdated
target_compile_options(base64 PRIVATE | ||
$<$<C_COMPILER_ID:MSVC>: | ||
/W4 | ||
/WX # All warnings as error |
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.
To my own projects, I usually add a PROJECT_WERROR
option to enable/disable warnings as errors (enabled by default).
That way, users have the possibility to ignore warnings.
This is useful for new compiler releases that introduce new warnings.
option(BASE64_WERROR "Treat warnings as error" ON)
target_compile_options(base64 PRIVATE
$<$<BOOL:${BASE64_WERROR}>:$<IF:$<C_COMPILER_ID:MSVC>,/WX,-Werror>>
)
Currently, only MSVC has warnings as error behavior.
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 concur.
What do you think about the warnings which are explicitly marked as errors? I don't remember adding them 😅
|
||
#elseif (_TARGET_ARCH STREQUAL "arm64" AND BASE64_WITH_NEON64) | ||
|
||
endif() |
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.
Perhaps add a else()
with a warning about an unknown arch?
else()
message(WARNING "Unknown architecture: ${_TARGET_ARCH}")
endif()
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.
A warning definitely makes sense.
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.
Does it though? Obviously there won't be SIMD acceleration, because SIMD instruction sets are architecture specific and one chose to compile for an alien one. Or is this more about not providing official support/ not regularly testing the pure C codec on that architecture?
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.
Another comment, shouldn't TARGET_ARCH
be HOST_ARCH
?
A target architecture only makes sense for a code generator (=compiler).
Here, we're just converting some sources to binaries (on a build machine to some host machine).
) | ||
|
||
install(EXPORT base64-targets | ||
NAMESPACE aklomp:: |
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.
Can you take another look at this suggestion?
#define BASE64_SYMBOL_PRIVATE | ||
|
||
#elif __GNUC__ >= 4 | ||
#define BASE64_SYMBOL_IMPORT __attribute__ ((visibility ("default"))) |
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 think import symbols don't need this.
#define BASE64_SYMBOL_IMPORT __attribute__ ((visibility ("default"))) | |
#define BASE64_SYMBOL_IMPORT |
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'm not an expert w.r.t. gcc symbol visibility; I looked at the GenerateExportHeader
output and noticed that they do define the import macro with said attribute (s. GenereateExportHeader.cmake:310
). However, I don't know the rationale.
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 interpretation is that adding visibility("default")
, you're instrumenting the compiler to export a symbol.
So adding this as a consumer will cause you to re-export the symbol.
@dotnwat Merging As I've written earlier in this thread, I feel conflicted about merging this PR because I have hardly any experience with (It's absolutely been on my ongoing mental to-do list for years and causing me quite some anguish as one of those points that you really need to do one day. I didn't just walk away from this. But that's not doing anyone in this thread any good.) So at a given moment I said I was willing to merge any
So that's basically why it's in limbo. As ashamed as I now am by all of this, I am seriously contemplating just merging everything sight-unseen and sorting out any breakage in later PRs. I tend to agree with you that any support is better than no support, and that once it's mainlined, it can be iterated upon.
EDIT: It works fine now. I was looking at an older version of the branch. Will play a bit with this then. Hollywood ending after all? |
One large problem with this PR is that everything is compiled without optimization. The result is that the code is incredibly slow. All the tricks that we do to get good performance (SIMD, fancy algorithms, aggressive inlining) are all for nothing:
Here's what it should look like when the benchmark tool is compiled with the old
This is clearly not a desirable state of affairs. Can Edit: the answer is yes, the optimization flags can be added to the block in |
/we4700 # Error warning C4700: uninitialized local variable | ||
/we4715 # not all control paths return a value | ||
/we4003 # not enough actual parameters for macro | ||
/wd4456 # disable warning C4456: declaration of 'xxx' hides previous local declaration |
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.
If all of these are legitimate issues with the code, I'd prefer to have them fixed rather than ignore the warning.
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.
There is currently one violation in the windows __cpuid
macro definition and its usage in codec_choose_x86()
. Sadly one can only disable the warning as a whole and not just it being treated as an error.
elseif(MSVC) | ||
set(COMPILE_FLAGS_SSSE3 " ") | ||
set(COMPILE_FLAGS_SSE41 " ") | ||
set(COMPILE_FLAGS_SSE42 " ") |
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.
Support for these levels are not selectable in MSVC?
Edit: to answer my own question: no, they are not. It's strange though, because what to do then? We can't really use the next best level, which is AVX
. But the default architecture is only SSE2
, so presumably these codecs would miscompile. Argh.
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.
To the contrary the SIMD intrinsics up to and including SSE42
are always available on the MSVC platform and cannot be disabled. This isn't an issue for MSVC because they don't utilize them for auto vectorization (unlike gcc).
CMake has four different build types (
I recommend using the more graphical |
@BurningEnlightenment I still think it's reasonable to set I'd like to add it unless it violates a core |
If there are optimizations that are only available at -O3 then it is reasonable to hard code that for all compilers. And you can even do that only for Release builds (which is always useful). I see on my system that -O3 is the default for GCC in cmake (with You can always use -O3 for everything and let exceptions be handled as they arise. Happy to help out a bit. |
####################################################################### | ||
# platform detection | ||
include(TargetArch) | ||
detect_target_architecture(_TARGET_ARCH) |
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.
CMake uses cmake toolchains for specifying the host architecture.
See CMAKE_SYSTEM_PROCESSOR.
Perhaps we should first try to parse CMAKE_SYSTEM_PROCESSOR
, and then try to run the compiler?
Using that approach, users can override the architecture in the case of a mis-detection.
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.
Or you could effectively transliterate the makefile into cmake (ie require users to set options). I'm all about making this as feature rich as possible, but it doesn't seem like it makes sense to wait on the perfect cmake build.
else() | ||
target_compile_definitions(base64 | ||
PUBLIC | ||
BASE64_STATIC_DEFINE |
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 find the _DEFINE
suffix weird: it's a definition anyways.
How about simply using BASE64_STATIC
?
I think we can keep the cmake gods happy by only doing "-O3" when building with a Release or RelWithDebInfo config. Something as follows: (untested) if(NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC")
string(REGEX REPLACE "([/-])O[0-2]" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REGEX REPLACE "([/-])O[0-2]" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE } -O3")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3")
endif() |
I just added an issue BurningEnlightenment#4 |
I am writing a Yocto project recipe for this library and tools and are basing it on the cmake. Because the high level of standardization saves me work. It would be nice to base the recipe of this repo instead of @BurningEnlightenment fork. Can we get it in and then optimize later?
The purpose of the debug build is that you can debug in a sensible way, so optimizations need to be disabled. If you really need to debug optimized code (and willing to suffer the big pain) there is the RelWithDebInfo flag. Has anybody seen a significant speedup from -O2 to -O3? |
Resolves #4
Thanks everyone for your patience, the @BurningEnlightenment Anyway, sorry this took so long. Let's iterate on this in new issues. |
I will leave the fork up for a month or two in order to allow people to migrate their CI/ package manager scripts gracefully. I'd also like to thank everyone involved for the reviews, feedback and contributions 🙂 |
Happy to see this merged. And great timing; I was just about to put up a PR to modify the relative include paths, as we are using Meson to integrate into our build system and it requires out-of-tree builds. |
Hi,
I just made a CMake script for the project, because I want to include it within another CMake project. The CMake script includes an install target (mostly for windows) and supports SIMD on the x86 platform (supporting NEON shouldn't be hard, but I don't need it). However I had to change
#include "config.h"
in order to support out of source tree builds. I hope you are ok with my solution.I successfully built the library on windows with mingw-w64 gcc 4.8.2 x86_64 and Visual Studio 2015 x86/x86_64/ARM.
My script is CC0 licensed and the
TargetArch.cmake
is distributed under a 2-clause BSD license (please note that no one distributes a cmake script in binary form, so the second clause concerning binary distribution is more or less meaningless).Fixes #70
Cheers,
Henrik