ixm-one / legacy Goto Github PK
View Code? Open in Web Editor NEWMake CMake less painful when trying to write Modern Flexible CMake (legacy)
Home Page: https://ixm.one
License: MIT License
Make CMake less painful when trying to write Modern Flexible CMake (legacy)
Home Page: https://ixm.one
License: MIT License
Currently, there is no way for us to have a more cohesive and more coherent API for creating targets in a given project. Additionally, we need to worry about tools such as vcpkg overriding add_executable
amongst other commands. To reduce this chance, we can add a more generic target()
command, with a variety of dynamic subcommands. This will allow us to make some operations easier (such as implementing commands for the generate()
API), while also allowing us to signal users when a target is added or created within an IXM Blueprint. This would also allow us to generate ALIAS
targets in the same target creation call.
Currently planned targets include:
target(PROGRAM)
-- This isn't different from add_executable
but is more inline with CMake naming conventionstarget(LIBRARY)
-- This will use add_library(SHARED)
call, to keep up with CMake's naming conventionstarget(ARCHIVE)
-- This will use add_library(STATIC)
, and keep up with CMake's naming conventionstarget(UNITY)
-- This will generate both a unity build file, and a library via add_library(OBJECT)
target(PLUGIN)
-- This will generate a module. This is done to keep C++ module and add_library(MODULE)
separate so as to not confuse users.target(IMPORT)
-- This signature will be used to generate imported targetstarget(INTERFACE) --
add_library(INTERFACE)`target(TEST)
-- add_test
wrappertarget(PHONY)
-- add_custom_target
wrapper.target(COMMAND)
-- add_custom_command
wrapper.target(LIST)
-- Lists all targets for the current project or given subdirectory. Useful for debugging (though in practice is not provided by the Debug API)We will also potentially have:
target(BUNDLE)
-- macOS bundle apptarget(FRAMEWORK)
-- macOS frameworktarget(TOOL)
-- like target(PROGRAM)
but will be compiled for the host if native compilation is ever supported under CMake's cross compilation model.target(SERVICE)
-- launchd/systemd related serviceThis list is subject to change but this currently works as a good start :)
Currently, the fetch()
command takes either a single TARGET
or multiple TARGETS
. This approach is frankly unnecessary and it would not be too hard to switch this to an IMPORT
argument that takes any number of targets. This is a blocker for the alpha release.
Currently CMake's default check_<lang>_compiler_flag
behavior leaves a lot to be desired. What we should do is the following:
-W
, -Wno
, and -Werror=
for GCC/Clang, /W
, /Wd
, /We
for MSVC)LINT
or similar subcommand.target(COMPILE_OPTIONS)
, target_compile_options
and add_compile_options
without issue.This will allow us to "generate" allow/deny/forbid lists of compiler lintings that users can enable/disable as desired. I personally think this will help out a great deal when working with "complex" projects.
The current way that the CPack module works is to generate a CPack configuration file after all calls to install()
within a project. With file(GENERATE)
this approach becomes superfluous and we can setup a way to generate the entire file based on generator expressions. This also means we'll have to make a dummy CPack.cmake
file so we can override its existence so we don't have subprojects break our build (as well as break the subproject)
Currently, we provide a series of API hooks, however nothing is truly uniform and there are some issues with the naming conventions. We need to permit users to
hook()
) to wrap all of these operations.AppImage is a pretty incredible tool and makes distribution of applications an absolute breeze compared to other forms of installation. However, CPack does not support generating an AppImage as a packaging format. It should! And it's doable.
Due to the recent removal of the experimental property
command (which wasn't even implemented), we are still in need of a custom define_property
to
target_copy_properties
command)Upon check(STRUCT)
succeeding for a named entity, it should not perform any other checks of the same entity, even if the "type" is different. (e.g., checking for both an enum and a struct of the same name).
The arghash (an internal variable used to check if changed arguments should cause the check()
to be rerun) is set to the found entity, but subsequent runs will be rerun due to the differing arghash.
CMake Version: 3.14.4
CMake Experience: Creator of IXM :)
Operating System: Any
Additional Tools: N/A
cmake_minimum_required(VERSION 3.14)
include(FetchContent)
FetchContent_Declare(ixm URL https://get.ixm.one)
FetchContent_MakeAvailable(ixm)
project(ixm-test BLUEPRINT Coven LANGUAGES CXX)
check(STRUCT std::errc COMPILE_FEATURES cxx_std_14 INCLUDE_HEADERS system_error)
check(ENUM std::errc COMPILE_FEATURES cxx_std_14 INCLUDE_HEADERS system_error)
Given a directory layout where src/*.cxx
generates a target and src/runtime/*.cxx
generates an OBJECT
target, anything "linked" against the ${PROJECT_NAME}
target is not actually set on the project's inner modules. There are really hacky and gross workarounds, but these need to be fixed in some capacity. Unsure exactly how this is going to be handled, but it's going to involve some trickery.
CMake currently has a bunch of executable/shell operations builtin available via execute_process(COMMAND ${CMAKE_COMMAND} -E <command>)
If this were abstracted, we could do some cooler things like task(ECHO_APPEND args...)
. This wouldn't allow us to have "futures" as it were, but it would be nice so that we could at least take advantage of the cross platform commands builtin into CMake.
Whether this command is called task()
, shell()
, or even just cmake()
is still TBD and needs some investigation into what feels most ergonomic.
If we could also somehow support pipelines, that would be killer :)
Currently, CMake only supports C# when using Visual Studio. I would much prefer the ability to use something like .NET Core or Mono. This support might include acquiring NuGet dependencies, linking the C# Runtime used to a C or C++ project, or simply building a few components as part of a larger project. We do not yet know the exact behavior. This will be determined as we attempt to implement initial support.
Calling include(CTest)
breaks a lot of stuff in what would be an otherwise normal build situation. One particular issue is that by calling enable_testing()
, we can no longer make a custom target named test
that also builds the unit test executables. In some places this build-and-run-tests target is called check
, however we would like cmake --build check
to be designated for clang-check
. As such, we need to override all the CTest related machinery, including generating a CTestConfig file. We can do this via file(GENERATE)
, much like we would like to in #6. One additional feature we get out of this is the ability to
ignore ctest altogether. This will let us do things like hook into other project's unit test runners, or submit additional information to a code coverage service, such as codecov.
While the Hook API, events, and dynamic invoking is "neat", it is already starting to cause performance problems on small projects. Moving to explicit if-elseif-else
chains is unfortunately the only remedy we can have.
This is extremely unfortunate. I was hoping to have the ability to let people extend IXM beyond it's initial capabilities, but this doesn't seem to be the case :/
This is now possible because we generate a bootstrap script that pulls IXM down via git behind the scenes so that it will automatically update as needed. This causes TONS of incorrect output and lots of failure. For example:
This NEEDS to be resolved before launch.
Hello ixm-one,
I recently noticed this interesting repository. However, I noted in particular that you have chosen to adopt a highly repressive Code-of-Conduct, in the sense that it mandates secret trials of contributors based on anonymous complaints, with no due process rights in such proceedings.
Now, I realize this is a one-person repository, so the whole scenario I described is moot. But that is also a reason why removing, replacing or amending the CoC document is super easy and does not require any organizational adjustment.
Currently, assign(home ? ENV{HOME})
succeeds in the DEFINED
check, but does not correctly dereference the variable. A small quick check is needed to see if the given values in ?
match ENV{} or CACHE{}. If they do, we must instead dereference them as $ENV{${value}}
, rather than ${${value}}
.
Currently, we have several functions that are useful for introspection and debugging a CMake script. These (currently) include:
inspect
locals
We should try to add additional features if necessary before the stable alpha, or at the very least, document commands that are debugging related, but might not be located in Modules/API/Introspection.cmake
(such as target(LIST)
)
Google's Go language is extremely ubiquitous at this point. However, cgo
support is absolute trash. It would be nice if, somehow, we could have CMake build a go project while also handling the correct cgo flag generation before compiling. This would make working with golang easier for everyone in the long run.
Currently we have added and removed a property()
command several times in IXM. It is one of the few areas where a wrapper might be useful, but for the most part does not offer anything specific.
That said, a property()
command for interacting with IXM's specific properties could potentially be more useful than the current convention of namespacing::every::single::level
with set_property
and get_property
. Particularly, this would allow us to have property "domains" and then abstract the details of how this is implemented away from the user. We could then also possibly use some kind of URI scheme for dividing items up. e.g., ixm::fetch::hub
currently must point to the command for the GitHub provider. However, there is no easy way for us to further customize fetch()
without using either a new parent namespace (e.g., ixm::settings::fetch
), or potentially clashing with a named subcommand. With a URI style scheme, we could easily do:
property(APPEND "fetch://hub/<setting>" <values>...)
property(GET <out-var> FROM fetch://hub/<setting>)
This will also further reduce our chances of colliding with other APIs.
NOTE: This could potentially be used as a solution for #20. If this is used as a customization hook API, and as it involves attributes of IXM, should be called attribute
to some degree.
Since I can't open an issue to ask a question, I had to classify it as an enhancement.
It would be awesome to not have to write by hand an export file for CMake libraries. The information is already provided in the CMakeLists.txt and a common pattern is to then go repeat the dependencies in the exports file.
Unsure if it exists.
Because it removes useless repetition.
By introspecting the properties of the targets defined under a project.
Are you willing to work on this yourself? Yes
How urgent is it to have this feature? Not urgent.
Is this feature request possibly out of scope for IXM? Not sure.
CMake does not currently support Kotlin. Neither the JVM nor Native compiler is designed to work with it in the slightest. Additionally, there is no language support for Java either. It is instead treated as a tool generator.
That said, Kotlin is, in my opinion one of the best ways to interact with Android. I'm about 30 years old and have never written a line of Java. I'd frankly like to keep it that way. Supporting Kotlin (or proving that 'native' support is unwieldy or requires a different approach) is sorely needed, especially before IXM hits its 1.0 release.
cinterop
tool)Currently, when CMake is cross compiling, it sets CMAKE_CROSS_COMPILING
to TRUE
. This also ends up meaning we can't compile any tools for code generation or otherwise when cross compiling. This is a huge limitation. However, there is a workaround and we can wrap it up into a special add_tool()
command.
This command will perform the following steps when CMAKE_CROSS_COMPILING
is ON
unset()
certain variables in the current function scope.set()
the current CMAKE_SYSTEM_NAME
into a temporary variableset()
the CMAKE_HOST_SYSTEM_NAME
to CMAKE_SYSTEM_NAME
set(CMAKE_PLATFORM_INFO_DIR)
to some predetermined directoryinclude(CMakeDetermine<LANG>Compiler)
set()
host versions of variablesdict()
and save to disk with some sort of hashtry_compile(PROJECT)
with flags that are stored in said dict()
(We cannot use generator expressions ๐). The project can either be the current one, or a separate one altogether.add_executable(name IMPORTED)
and set the path to the given target.The above is just the tip of the iceberg. There are many MANY things that need to be taken into account, such as, but not limited to:
This is going to be a big feature, but it is EXTREMELY useful. That said, it's low priority until everything else is stable.
SDL2 is a lovely library, but the default FindSDL2.cmake
files that are out there leave a lot to be desired. There's no reason we can't provide a file to help people along the way. It should also provide support for finding the various SDL2 components, such as TTF, image, net, mixer, etc.
Having a generate(FIND)
command to automatically generate a FindXXX.cmake
file would be extremely beneficial.
This is contingent on us treating generate()
as a command that is not only used to help with file(GENERATE)
operations. In our case, this might be better as a new command configure()
, but some investigation work is needed.
Currently we have this bizarre setup for creating custom "dependency references". While the idea is neat, and inspired directly by ExternalData
, in practice, we don't really need it thanks to our dynamic subcommand lookup. As a result, we're wasting time parsing these recipes instead of just passing them to the various subcommand providers.
We also should permit setting all options found within the DICT
operation as parameters once again. It's nice to have a 'default' dictionary setup, but again, in practice, it is more trouble than following existing conventions.
Currently we do not:
Protect against carriage returns (which is needed because CMake OF COURSE makes the bad choice to write them out in all cases on Windows).
Solution: Use the IND
C1 control code as an escape/replacement. It isn't being used any longer, comes right before the NEL
C1 control code and pairs well with the CR
+ LF
combo.
The STX
/ETX
combo is useless and can't easily be used at all. Do we want do escape quotes? Things seem to round trip correctly despite my best efforts to ABSOLUTELY mess up CMake.
We do not have forward compatibility for reading multiple files out of a single file. This should be rectified, if I'm being honest. It would be nice to just dump a huge project into one file for analysis. It should have a different extension however. We could always use IXD (IXM Extended Database?). I'll look into it.
Currently, we do have some way to "generate" events. Doing so allows users to react to changes in the environment when necessary. In our case, we need to provide the following subcommands:
event(ADD)
-- Registers commands to eventsevent(RM)
or event(REMOVE)
-- Unregisters a command to eventsevent(EMIT)
-- Signals an event with some dataThis issue is an umbrella issue and a blocker for the alpha release. It aims to act as an audit to ensure that the mentioned APIs below are feature complete and not missing functionality (as this has on occasion caused me embarassment when I go to show something and realize that the code has been temporarily disabled due to a bug elsewhere)
Luckily, having this umbrella issue will allow us to also know what general documentation for a given section must be written.
Some work is needed to also add the ability to deserialize an IXM file onto any set_property(<type>)
. This will let us deserialize IXM files into add_test calls as desired.
LOAD
/SAVE
(Deserialize and Serialize to and from the IXM format)JSON
(Serialize a dictionary to the JSON format) -- Honestly, this should be removed.APPEND
/ASSIGN
/CONCAT
(Modify values within the dictionary)REMOVE
/CLEAR
(Remove specific key-values. Completely empty the dictionary)KEYS
(Return a list of all keys in the dictionary)GET
(Return the value associated with a key in a dictionary)TRANSFORM
Equivalent to the cmake list(TRANSFORM)
subcommand, but operates on a key's valueFRAMEWORK
-- Can find an Apple Framework library. Versions are not taken into accountPROGRAM
-- Can find an executable program, and optionally its versionLIBRARY
-- Can find a library (static or shared) and possibly its versionINCLUDE
-- Can find a header file, possibly its version, and create an INTERFACE
library (this behavior should be placed into LIBRARY
, however)This API is still in flux and does not quite exist in a "stable" manner. The idea is to replace the target_XXX
commands such that we do not need to override them while also allowing custom user defined hooks without having to break existing APIs. No idea if this will actually work well. We'll leave this section blank as #18 is still open.
These are commands related to common project settings, such as options, features, and 'optional dependencies'. Currently the existing API/Project.cmake
file is an absolute mess. Better support is desperately needed :(
with()
-- Build ${PROJECT_NAME}
with the provided dependency if the given option is set. Generates an option named ${PROJECT_NAME}_WITH_${dependency}
. If the project is a so-called top level project, a WITH_${dependency}
name is generated as well.feature()
-- Build ${PROJECT_NAME}
. Currently this is just an option added as ${PROJECT_NAME}_ENABLE_${feature}
, however it could be expanded to do things such as automatically add lint build flags (for either the primary component or a sub-component such as docs or unit tests) and to add settings to a configure header.workspace()
-- This should be a special version of project()
intended for more monolithic projects. This will then prepend the workspace name to each subproject. It'll also allow us to declare that this "workspace" is not meant to be used as a subdirectory. Though, this could lead to people assuming that a workspace based project is a "bad actor" in the world of CMake.The logging API is working fairly well. A few options should be dropped to work better with CMake's newer --log-level
settings, but otherwise it's going very well. One thing that is still needed is
Otherwise, we'll leave this section blank for now.
This API is currently used internally for the invoke()
command. While dynamic command invocation is neat and all, its something that should be phased out within IXM. This means getting rid of the event API, which will be mentioned later in this issue. That said everything is working quite well, and is quite simple, though the inspect()
command itself needs some love as its quite a nightmare to view at the time of this writing:
macro (inspect)
foreach (@inspect:var ${ARGV})
set(CMAKE_MESSAGE_INDENT "${CMAKE_MESSAGE_INDENT}${\@inspect\:var}: ")
if (DEFINED ${\@inspect\:var})
list(LENGTH ${\@inspect\:var} @inspect:length)
if (@inspect:length GREATER 1)
string(JOIN " " ${\@inspect\:var} ${${\@inspect\:var}})
endif()
_message("${\@inspect\:var}: ${${\@inspect\:var}}")
else()
_message("${\@inspect\:var}: $<UNDEFINED>")
endif()
void(CMAKE_MESSAGE_INDENT @inspect:var @inspect:length @inspect:prefix)
endforeach()
endmacro()
Hopefully it can be cleaned up in time for the alpha release.
Because of its dynamic invocation internally, we need to get rid of this. It's not even used internally, except for the still in flux Target API. Mark it up as a failure that CMake is such a dumpster fire when it comes to actually usable concepts. :/
This is kind of a mistake in hindsight. It's nice to do things like import(IXM::API::*)
, but at the same time only we currently use it, the behavior for it hides errors for includes, and it makes it difficult to know if a file is even being used when it might be 'optional' to begin with. Whether it exists in the alpha release or not depends on whether I have time to kill it now and I kind of hope I do.
That said, declaring a "MODULE_ROOT" isn't such a bad idea as it allows a better extension approach when adding additional libraries to support or extend IXM (such as adding tooling support or generation)
This was basically butchered recently because of the additions made in CMake 3.16. Its still useful, as we can generate flex, bixon, protobuf (sort of... some work is needed to keep things nice and clean here because the cmake support for protobuf is a shitshow). The big point is that we can generate a response file from a target (not source files, because generator expression limitations), which makes generating source files from other tools easier! hooray!
But we still need an overhaul for this...
This is in DESPERATE need of an major overhaul. Current issues include
$XDG_DATA_HOME
support!) so that debug and release builds pull from the same location. With CMake 3.17 adding multi-config Ninja build support, this is important as it'll reduce pain for many users, while still allowing the vendoring of assets and better CI integrationAdditionally CLONE
should be enabled by default, and instead something like CACHE
or DOWNLOAD
should be an option for when you can download a package instead of just clone it via git or hg or svn or whatever.
I like it! It's been useful for setting certain values and keeping properties inheritable in a proper manner such that a top-level project is always in charge. However I'm unsure if users are going to enjoy it or not. Additionally, it's an important command and should be placed into API/Core.cmake
.
This is fine as is. The hard part is placing everything into the prelude and keeping it readable. I'm unsure how to proceed with this portion of it.
This is the "recommended" blueprint for new projects, as an upgrade path will be provided when the actual coven build system is released in a few years (yes, years... I'm a busy girl). A lot of work is needed here.
CTestConfig.cmake
file is needed. This will let us have better control over how our files are generated (in other words, we can use the IXM binary format when generating a CTest build, and also use a custom test
target that actually builds the project before running the tests)This one is much simpler, as it's ONLY used to generate a single add_library(MODULE)
per project, and is intended for use with the brujeria python library. The hard part of course is making sure folks have an update to date IXM instance when building from source, but we can add some CI tooling to help ensure that.
IXM is currently a loose collection of ideas that need to be locked down and finalized before the "stable alpha" release. We also have a large number of deprecated modules and files that have been kept around for historical reasons. These need to be removed ASAP.
This concludes the umbrella alpha release issue (for now).
fetch()
should (optionally) store downloads in a cache directory
fetch()
will currently do what the FetchContent
API does, which is place all source and build dependencies in the build directory.
FetchContent supports manually setting the source and binary directories. To reduce disk footprint (as well as support caching dependencies in CI), we should follow the general XDG naming guidelines for the given cache.
This might take a bit of work, but in the end we'll have an XDG-like function and properties for customization. The important part is getting the CACHE directory set for use. It's currently up for debate if the XDG functions should be made available to everyone.
As wonderful as Rust's cargo
is, not all projects are mono-lingual. It would be extremely great if a C++ or C project could link to an existing Rust project. Even better, being able to build a rust program that is then used for an add_custom_command
or add_custom_target
would be fantastic!
Yes, the https://docs.ixm.one link in the webpage and README appears to be broken.
Firefox and Chrome fail to connect to the server, and I cannot ping
it:
$ ping https://docs.ixm.one
ping: https://docs.ixm.one: Name or service not known
Nope, sorry.
This will also allow us to improve the command to perform multiple lookups. Furthermore, it can also be a function, instead of a macro.
This would help with #15
Due to issues brought on by CMake 3.16's support for Unity builds and precompiled header support, we can't keep the IXM implementation of these around. They are, unfortunately, incompatible and will break when moving between CMake versions. Thus, sadly, 3.16 will have to be the minimum version for IXM's initial alpha release :(
Writing emoji in build files is usually a red flag (if only that were an actual emoji...)
CMake does not provide a proper mechanism for read only properties, thus we need to discourage users overwriting them in their build files. CMake is also byte safe, so we should be able to use emoji without issue.
Current list of properties to place under emoji:
attribute()
subcommands (emoji TBD)get_property
internally. (๐ into what this entails...)Currently, we provide a small set of 4-bit colors for foreground printing. There is, honestly, no reason people cannot have a custom RGB colorization. Taking a page from the python pastel
package, we'll have the builtin print()
function perform automatic colorization via special <rgb>text</rgb>
tags. The actual syntax for how to get high intensity colors and such needs to be decided upon, but preliminary tests show that this should be a simple "find-replace" with CMake regex, as awful as that regex implementation might be. :)
The current find_package(BISON)
implementation leaves a lot to be desired. We could do way better by supporting a generate(BISON)
command. This will also have to work in conjunction with a generate(FLEX)
command as well. The actual work for this might be pushed until after the pre-alpha release.
To allow users to understand what the "core" API calls for IXM are, each one should be located directly within the Modules/API
directory. Currently the following commands do not meet this requirement:
dict
inspect
invoke
var
(This name is unhelpful, and should be replaced)upvar
genexp
glob
(Perhaps this function should be removed altogether)import
module
blueprint
log
parse
print
success
failure
global
internal
cache
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.