-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Refactor third-party libraries to build from source on Linux #5706
Conversation
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.
Best approach to make sure the config files are a good starting point is to make sure there're as few -dev
packages installed on the Ubuntu box.
@Smjert and I will probably re-generate them using the custom toolchain and then make a diff and look at what changes.
azure-pipelines.yml
Outdated
inputs: | ||
workingDirectory: $(Build.BinariesDirectory)/build | ||
cmakeArgs: --build . --target format_check | ||
# Temporary; this is disabled because it complains about the config.h files |
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.
We need to enable this back on, but we should prevent generated config files from causing this check to fail
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 that the easiest way is to add an ignore folder option (if it's not already there) in the script that checks the format.
We can ignore the entire libraries folder and be done with it.
Though if we want to have it more flexible, we should also probably add an option to specify single files.
|
||
# The formula will be configured with the C_FLAGS and CXX_FLAGS parameters; we should | ||
# forward them to the configure script when possible | ||
message(WARNING "TODO: Use C_FLAGS") |
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.
We are not yet passing the compiler/linker flags to the openssl configure script. We receive them as C_FLAGS and CXX_FLAGS from the main osquery project
BUILD_COMMAND | ||
"${CMAKE_COMMAND}" -E env CC="${CMAKE_C_COMPILER}" | ||
"${CMAKE_COMMAND}" -E make_directory "${CMAKE_INSTALL_PREFIX}/etc/openssl" && | ||
$(MAKE) depend -j 10 && |
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.
This is a totally arbitrary value that we should make configurable and default to a sane value
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.
You should be able to remove -j 10
right now with the use of $(MAKE)
.
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 this use of $(MAKE)
within the BUILD_COMMAND
property work with Ninja as the generator?
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.
The formula system was implemented using custom commands that are triggered when the required library files are referenced. The build command is executed in a new environment and is detached from the main project. It should work in theory, but I didn't test it yet.
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 had to change to make
because $(MAKE)
is only valid if the generator calling the command is make; that's what you use for coordinating with the jobserver and avoid to spawn too many jobs.
With the change it will spawn more jobs than you required when building osquery, but it shouldn't be too much of an issue, especially for building openssl.
function(opensslMain) | ||
generateMetadataTargets() | ||
|
||
if(NOT DEFINED thirdparty_zlib_INCLUDE_DIRS OR |
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.
The metadata exchange mechanism relies on the fact that if the required parameters are missing the configuration step will still succeed (without creating the formula target)
endif() | ||
|
||
# Generate the formula runner that will actually build the libraries | ||
# TODO(alessandro): Change it so we use a completely new environment |
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.
We should launch the build command with a completely clean environment
A series of things still to do:
Glibc 2.28 deprecated some macros and moved them into a different include if one really needs them:
This shouldn't be a problem when using the custom toolchain, but if we also want to support building with system one, this has to be fixed. |
Some overall notes
|
@@ -0,0 +1,210 @@ | |||
# Copyright (c) 2014-present, Facebook, Inc. |
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.
The path libraries/cmake/facebook/modules/api.cmake
doesn't make a lot of sense.
Alternatively, move this logic into /cmake/
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 don't feel strongly about this. Your call on where api
and utils
are located.
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 have stored the APIs there since they are layer-specific. Since the libraries folder (at least on the CMake side) is self-contained and not used directly by the main project, I ended up saving the file near the entry point (the find_package handlers).
We can move it elsewhere, keeping in mind however that the FindPackage script should keep using relative paths
BUILD_COMMAND | ||
"${CMAKE_COMMAND}" -E env CC="${CMAKE_C_COMPILER}" | ||
"${CMAKE_COMMAND}" -E make_directory "${CMAKE_INSTALL_PREFIX}/etc/openssl" && | ||
$(MAKE) depend -j 10 && |
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.
You should be able to remove -j 10
right now with the use of $(MAKE)
.
BUILD_COMMAND | ||
"${CMAKE_COMMAND}" -E env CC="${CMAKE_C_COMPILER}" | ||
"${CMAKE_COMMAND}" -E make_directory "${CMAKE_INSTALL_PREFIX}/etc/openssl" && | ||
$(MAKE) depend -j 10 && |
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 this use of $(MAKE)
within the BUILD_COMMAND
property work with Ninja as the generator?
The approach is great, thanks for flushing this out! My inline comments are low-pri. Take a look at the 1,2,3 points I made in the overall PR comment. If they are reasonably addressed then I am good-to-go on this! |
|
da0b237
to
a4a5937
Compare
Thanks for having a look at it. |
Expanding more on Stefano's answers: I captured the .cpp/.c files in the configure-based libraries while trying to remove the most obvious |
So you were right, @alessandrogario fixed that. |
Sorry about the noise but you'll need to rebase one more time for changes to |
b1e846a
to
e593ed4
Compare
|
We can iterate on this in follow up PRs as well. |
FYI, I was trying to speed up the checkout in my last commit to this branch. Feel free to overwrite/replace/remove if it messed something up or there are fundamental issues with the changes. |
2f5680b
to
353a039
Compare
I've rebased on master and fixed a thing, otherwise even the previous build would fail. |
For the only test that's failing, it seems that zlib is not using the correct CRC32 implementation for gzip. |
So the issue is a bit tricky: I tried to avoid to compile that symbol, but it's used by |
Interesting, can we use linker flags instead of patching? I’m not sure what flags or if this is possible, but we should look. |
I've checked, using the preprocessor you can pass |
Great progress, how are we doing on the list of TODOs? Should we squash everything into a small commit set? |
A single commit might be good too, or at least a very small set, to make bisecting easier. |
If possible we wanted to preserve the contribution of everyone, even though to be honest I'm not really sure how much is possible, given that our commits are mixed and sometimes they directly depends on each other. I've updated the TODO list for what there's still to do, I'll update it again if I missed something.
|
Add a way to compile third-party libraries from source instead of downloading prebuilt ones. Each library source code is downloaded with git into a submodule at configure time, in response to the find_package(library_name) CMake call, except for OpenSSL where the official source archive is used. Each submodule is attached to a release tag on its own upstream repository. All the libraries are built using CMake directly, except for OpenSSL which uses a formula system, which permits to build libraries with a separate build system when there's no easy way to integrate it directly with CMake. This new dependency system determines which library is fetched from where using the concept of "layers". Currently we have three of them: source, formula, facebook, where the last layer represents the pre-built libraries. The provided order will be used when looking for libraries. A system to patch submodule source code has been added and it's currently used with googletest, libudev and util-linux. Patches should be put under libraries/cmake/source/<library name>/patches/<submodule>, where <submodule> is often one and is "src", but in other cases, like AWS, there are multiple with a more specific name. If for whatever reason the submodule cloning or the patching fails, the submodule has to be unregistered and its folder should be cleared. This should be achievable with "git submodule deinit -f <submodule path>" Following some other changes on existing functionality: - Changed the CMake variable BUILD_TESTING to OSQUERY_BUILD_TESTS to avoid enabling tests on third party libraries. Due to an issue with glog the BUILD_TESTING variable will be always forced to OFF. - Moved compiler and linker flags to their own file cmake/flags.cmake - Moved all the third-party CMakeLists.txt used for pre-built libraries under libraries/cmake/facebook - Added the --exclude-folders option to tools/format-check.py and tools/git-clang-format.py, so that it's possible to ignore any third party library source code. - The format and format_check target use the new --exclude-folders option to exclude libraries/cmake/source from formatting. - The test and osquery binaries are properly compiled with PIE (#5611) Co-authored-by: Stefano Bonicatti <stefano.bonicatti@gmail.com> Co-authored-by: Teddy Reed <teddy@casualhacking.io>
dcab26a
to
943ed1a
Compare
This PR converts all the libraries required by osquery to source modules, by converting the Makefile-based build systems to CMake.
All the libraries have been rewritten, except for OpenSSL, which is implemented using a formula-based system similar to the old one we were using with brew.
Each library resides in a git submodule that is directly attached to a release tag on the upstream repository. Each submodule is fetched at configure-time in a lazy way, in response to the find_package(library_name) CMake call.
The new dependency system implements "layers"; they are configurable, and determine which library is fetched from where. We currently have three layers implemented: source, formula, facebook. The provided order will be used when looking for libraries.