-
Notifications
You must be signed in to change notification settings - Fork 262
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
Optimize CMake install targets and add top-level CMakeLists.txt #309
Comments
The current SuiteSparse cmake projects are referring to others by I created a branch to demonstrate how we use can CMake properly. Generally, I dropped all set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${SUITESPARSE_DIR}/lib/cmake/")
find_package(suitesparseconfig REQUIRED)
find_package(colamd REQUIRED)
find_package(amd REQUIRED)
find_package(btf REQUIRED)
find_package(klu REQUIRED) #these find packages can be fused if we define a top-level package
target_link_libraries(circuit SuiteSparse::klu) # SuiteSparse::klu_static if you want static lib
# that is all, no need to add individual modules as dependency is recorded in SuiteSparse::klu Finally, I can import KLU with less trouble. |
This seems like it may be related to #267, possibly? |
Yes. The differences are:
|
Regarding your point 1: IIUC, @DrTimothyAldenDavis needs the variables that are currently set in the Points 2 and 3 sound interesting. Especially, point 2. Do you mind if I'd include that at some point in #267. (See #267 (comment).) I can't comment on point 4. |
While that is kind of true, there can still be cases where CMake can't generate build rules automatically from targets. ISTR that the use-case here was to gather the compiler arguments to build .mex files with Matlab/Octave. It is possible to gather those arguments from the CMake targets. But it requires a bit more than a couple of lines to get that information for all targets and with all generators. I agree with @DrTimothyAldenDavis that it is easier to have that logic in one place and keep it available for all downstream users instead of sprinkling it across different projects.
I'm not sure whether we are talking about the same thing here. There are probably better sources to explain the issue with overlinking shared libraries. But let me try to give a short example trying to illustrate it: |
As long as you want to link to klu, link to btf and other stuff cannot be omitted. Your example is strange to me, if A.dll changes that means the function name has been changed, and B depends on A, that is to say, B must be rebuilt after A changes the APIs because it refers to A's APIs at runtime. You simply cannot use old B with new A.dll. If you think you can change A's API without rebuilding B, it creates a timed bomb for B to throw an "unknown reference to function xxx". If I link Klu to my program statically, all other modules are assumed to be called because Klu will call them and that is the case for the static library. You cannot even build a klu program without the link to static libraries such as btf even if your program use nothing from btf. Remember, link public or private to static libraries are always public: If I link KLU to my program dynamically, klu must be assumed to call other dlls, so that I have to make sure all dlls are there and APIs are consistent. If the depended btf dll is changed, and it changed its API function name that is used, then the outdated KLU will fail when my program calls KLU routines. Therefore, If program In our case, cmake doesn't care about the SONAME because the cmake targets are installed by cmake, the update-to-date targets are always found when i use find_package. CMake targets are used for cmake C/C++ projects. If you are talking about mex, i don't find anything special in the current I didn't touch anything in |
Please read carefully. I never wrote that. My point was whether application
Again please read carefully: I explicitly wrote about shared libraries in the example - not static libraries. And if you'll have a look at #306, you'll find that the dependencies for static libraries are kept
That is incorrect when using shared libraries afaict. There is no such requirement. And best-practices recommend against it.
Even if the |
I think you are right. Dynamic libraries are not using the same rules as static libraries. I can see the real problem is not just recompiling but duplicating symbols if Linking dlls privately brings a question of whether the klu's dependent dlls should be hidden from users. For mex, my comments were they should be added with additional configurations. Building a mex library should be no different from building a regular c/c++ program. What I find is we can use If i maintain downstream projects, I dislike special manual configurations in the building process and I prefer a cmake target with default behaviors. I feel building a mex doesn't have differences from linking to a normal C library so no special configurations are needed. |
I agree. But I also agree with @DrTimothyAldenDavis that there should be at least a transition period where downstream can continue using the current cmake variable. Maybe that "transition period" should even be indefinite.
Maybe I'm misunderstanding what you mean. But isn't that very similar to what is proposed in #267? (E.g., https://github.com/DrTimothyAldenDavis/SuiteSparse/pull/267/files#diff-6c61cdc8330af33a389d42be594819a8f12070dd984139abe8ded32fc740ad24R38 |
I think the transition period can be keeping the old What I mean is we should do it in the opposite way: keep the auto-generated target as default However, I realized the old @PACKAGE_INIT@
set ( @PACKAGE_NAME@_DATE "@DATE@" )
set ( @PACKAGE_NAME@_VERSION_MAJOR @VERSION_MAJOR@ )
set ( @PACKAGE_NAME@_VERSION_MINOR @VERSION_MINOR@ )
set ( @PACKAGE_NAME@_VERSION_PATCH @VERSION_SUB@ )
set ( @PACKAGE_NAME@_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_SUB@" )
include ( ${CMAKE_CURRENT_LIST_DIR}/@[email protected] )
# The following is only for backward compatibility with FindKLU.
set ( _target_shared @DYNAMIC_LIBRARY_NAME@ )
set ( _target_static @STATIC_LIBRARY_NAME@ )
set ( _var_prefix "@PACKAGE_NAME@" ) to have a more universal template for all targets. Do you think this is better? Also, we can modify project names to capitalized project names and make a consistent set ( CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}
${CMAKE_SOURCE_DIR}/../AMD/build
${CMAKE_SOURCE_DIR}/../BTF/build
${CMAKE_SOURCE_DIR}/../CAMD/build
${CMAKE_SOURCE_DIR}/../CCOLAMD/build
${CMAKE_SOURCE_DIR}/../CHOLMOD/build
${CMAKE_SOURCE_DIR}/../COLAMD/build
${CMAKE_SOURCE_DIR}/../SuiteSparse_config/build ) Because we should not decide on building directories when the building directories can be changed by users. Meanwhile, there is a chance to collide with system packages. If we want to specify the directories for |
I was considering that. However, these variable names aren't consistent across the different libraries. So instead of coding a bunch of exceptions, I decided it would be cleaner to just handle that on a per-library level.
Afaict, those are only there to simplify building in a "common" source tree. If users prefer to build in separate trees, they'd need to set
I agree. But I think that can be handled independently (i.e., in a separate PR). |
That is what we want to improve, make them more consistent. But for example, if the system has an |
I guess you are referring to the
Thanks for pointing that out. Re-reading the documentation, I think we should be setting |
Obviously these set ( KLU_DATE "Jan 17, 2023" )
set ( KLU_VERSION_MAJOR 2 )
set ( KLU_VERSION_MINOR 0 )
set ( KLU_VERSION_SUB 3 ) should be set ( DATE "Jan 17, 2023" )
set ( VERSION_MAJOR 2 )
set ( VERSION_MINOR 0 )
set ( VERSION_SUB 3 ) And why we are setting versions here and there? why not use the existing CMake project to obtain these versions? Besides, I think we should add . I think a top-level cmake file is quite useful if we want to improve the overall user experience. I don't know what is the difference between If we really want to assign fixed paths for internal find_packages, we may directly provide paths like this: find_package (<PackageName> PATHS paths... NO_DEFAULT_PATH) |
I'm not going to argue with you whether the current VERSION variable names should be kept or not. Imho that is completely independent of whether IIUC, the main difference between
Didn't you write earlier that you think building the libraries independently in separate source trees or build trees should be possible? |
Yes, it is not only possible but also verified. I reconsider this My idea is to provide a temporal prefix by commands such as But local libraries may still co-exist with system-installed libraries. In this case, we set the I think these can be achieved by adding a config to _DIR has higher priority than CMAKE_PREFIX_PATH because "If _DIR has been set to a directory not containing a configuration file CMake will ignore it and search from scratch." Currently, I have no time to create a PR but at least I recorded some todos here. I think the current multiple PRs should be merged first to allow further PR changes. |
The build and install steps need to be kept separate. Otherwise, distributors will run into trouble. You can't rely on a mechanism that requires install steps interleaved in the build process or you will cause a lot of headaches.
Please have a look at the documentation for the search order of |
You are just using the same building setup as end users if use the installed prefix to find_package. |
@DrTimothyAldenDavis, hope you don't mind a quick comment on the CMake support here (didn't seem worth of a new issue). I noticed various files were added as wrappers with Since I couldn't find anyone commenting about it, it's worth mentioning CMake allows reusing the same file with different constants defined. For example, we use object libraries for our custom build in our "KLUSolve" wrapper. Maybe there are other reasons for the file approach. If so, sorry for the noise. (By the way, this wrapper I mentioned will be retired soon and the CMake support in SuiteSparse will help simplify things.) |
Thanks for the feedback. Cmake is a complex language and I've tried to keep my usage of it as basic as I can. I wasn't able to figure out how to use cmake to compile a file multiple times. I used to do that in my old Makefile setup, before using cmake. From all the cmake documentation and examples I saw, it seemed to work best with each file being compiled just once. Thus the introduction of files like this one: https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/dev/COLAMD/Source/colamd_l.c I've gotten this method to work, and it seems robust, so I'll stick with it for now at least. |
@DrTimothyAldenDavis Yeah, it's not really an issue. Indeed CMake is complex and some features are not widely used, hence few examples. |
That would not work for several reasons: (1) it changes the library structure (-lcolamd includes both the 32-bit integer API and the 64-bit API, but this approach creates multiple libraries), and (2) it would fail for more complex packages such as UMFPACK, which uses a mix of files (some compiled once, some twice, some 4 times). |
Most of these related issues are now resolved in the dev2 branch, to appear soon as SuiteSparse v7.2.0.beta, except for the top-level CMakeLists.txt file. That's a useful extension that I'll consider for the next version (say v7.3). So I'll leave this issue open until then. |
There is a proposal for a root CMakeLists.txt in #415. |
I think this is now fixed in SuiteSparse 7.4.0, in the default dev branch of the SuiteSparse repo. I'll release a 7.4.0.beta1 soon. Can you give it a try? |
Thanks for all the feedback. SuiteSparse 7.4.0.beta1 has now been released (as a pre-release), with a top-level CMakeLists.txt file. I think this issue is now resolved, but can you give it a try, @chengts95 ? |
Fixed in SuiteSparse 7.4.0. |
I got Also, |
Thanks for reporting these issues. |
I have figured out the causes for multiple rules, this is because on Windows, |
That is what I was thinking, too. |
I can do it when I have time, and also I may check how to compile it on Mac OS with an M2 arm CPU. It seems that clang for windows has a different link flag for OpenMP, and the link to OpenMP::OpenMP_C didn't add |
@chengts95: I opened #749 and #750 to keep track of the issues you reported. (Took about 2 minutes. Not sure why you couldn't do that yourself...) |
Is your feature request related to a problem? Please describe.
Currently, the project consists of many small dependent CMake projects. But there is no top-level CMakeLists.txt which is very inconvenient and inconsistent especially on Windows.
Moreover, "Find*.cmake" was designed to find third-party libs built without CMake, these files are cumbersome and not stable. The current user experience is like the project is not much easier to use than the pure makefile age.
Describe the solution you'd like
I propose using ExternalProject command from CMake to build all projects and maybe create a universal CMake install target.
Moreover, exposing the installed CMake targets via "*Config.cmake" files can significantly simplify the building process and increase the usability of the library.
Describe alternatives you've considered
I believe the above method is relatively easy and useful. Maybe there is a better way to create a simpler process.
The text was updated successfully, but these errors were encountered: