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

Implement CMake build system #647

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

Conversation

Timmmm
Copy link
Collaborator

@Timmmm Timmmm commented Dec 18, 2024

This is a draft of a CMake build system. There are a couple of caveats which is why it is a draft:

  • Doesn't include RFVI, JSON docs, formal stuff, etc.
  • Commit is quite messy - includes moving files around and upgrading softfloat; I'll split that out in future.

However this should demonstrate the direction I think we should take. It has significant advantages:

  • IDE support is perfect, since it generates compile_commands.json. You can even go-to-definition to the generated code (I can demo this in the meeting if people want). Lots of IDEs also understand CMake and CTest.
  • Building all the emulators and running the tests is easy, parallel, and can generate an XML test result file (I haven't tested this though).
  • Better Windows support, e.g. CMake can generate Visual Studio project files.

There are several things that I think we should probably do before this which would make it a lot nicer:

@Timmmm Timmmm mentioned this pull request Dec 18, 2024
CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Overall this is looking good!
I've left a few CMake comments, but it's quite hard to review with the softfloat upgrade included here.

@Timmmm Timmmm force-pushed the user/timh/cmake branch 2 times, most recently from bad1feb to 80d0154 Compare January 2, 2025 15:02
@Timmmm
Copy link
Collaborator Author

Timmmm commented Jan 2, 2025

Thanks for the review! I've split the other changes out into separate commits, so the CMake stuff is just the last commit now and hopefully easier to review.

I might drop the upgrade to softfloat actually since it didn't really change the code and hopefully we'll remove it at some point anyway in favour of the pure Sail implementation.

@jordancarlin
Copy link
Collaborator

I think it probably makes sense to skip the softfloat upgrade for the reasons you mentioned, but if we do decide to keep it I have some suggestions so that you don’t have to modify their Makefile.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Regarding the commit that suggests bundling GMP - we could also use https://cmake.org/cmake/help/latest/module/ExternalProject.html#examples to build a known version statically (either opt-in or by default).

@@ -1,428 +0,0 @@
# Select architecture: RV32 or RV64.
Copy link
Collaborator

@arichardson arichardson Jan 2, 2025

Choose a reason for hiding this comment

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

Could keep the makefile for the targets that aren't supported yet and just defer to CMake by default?
e.g.

csim: $(BUILD_DIR)
    cmake -S . -B $(BUILD_DIR) -GNinja -DCMAKE_BUILD_TYPE=Release && ninja -C $(BUILD_DIR)

Or to avoid needing ninja:

csim: $(BUILD_DIR)
    cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Release && $(MAKE) -C $(BUILD_DIR)

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

A few minor comments but generally looks good to me.

.gitignore Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Show resolved Hide resolved
emulator/CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
cmake/extra_fast.cmake Outdated Show resolved Hide resolved
@Timmmm
Copy link
Collaborator Author

Timmmm commented Jan 3, 2025

if we do decide to keep it I have some suggestions so that you don’t have to modify their Makefile.

We aren't actually using their Makefile at all with the CMake version; I just kept the modifications so that it compiled as a standalone commit. I'll just remove the upgrade anyway though.

@arichardson I think you put a comment somewhere that I can't find now about keeping the Makefile. I think I'll just try and implement all of the features currently in the Makefile before merging this, rather than have two build systems...

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Adding all the other targets may take quite a while, maybe easiest for now to add CMake support and remove targets from the Makefile as we port them over?

E.g. this PR just removes the csim target (or rather have it defer to CMake cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Release && $(MAKE) -C $(BUILD_DIR)) and then later commits add the extra features? Otherwise I worry this will be a long standing feature branch that never gets merged.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 9, 2025

Adding all the other targets may take quite a while, maybe easiest for now to add CMake support and remove targets from the Makefile as we port them over?

E.g. this PR just removes the csim target (or rather have it defer to CMake cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Release && $(MAKE) -C $(BUILD_DIR)) and then later commits add the extra features? Otherwise I worry this will be a long standing feature branch that never gets merged.

Doing CMake incrementally makes sense to me, but I'd rather not incrementally remove things from Makefile. It's annoying to have to use both depending on what you want to do. I don't really see the benefit of it. Just leave Makefile alone until it's entirely subsumed by CMakeLists.txt and then delete it.

@arichardson
Copy link
Collaborator

Adding all the other targets may take quite a while, maybe easiest for now to add CMake support and remove targets from the Makefile as we port them over?
E.g. this PR just removes the csim target (or rather have it defer to CMake cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Release && $(MAKE) -C $(BUILD_DIR)) and then later commits add the extra features? Otherwise I worry this will be a long standing feature branch that never gets merged.

Doing CMake incrementally makes sense to me, but I'd rather not incrementally remove things from Makefile. It's annoying to have to use both depending on what you want to do. I don't really see the benefit of it. Just leave Makefile alone until it's entirely subsumed by CMakeLists.txt and then delete it.

That sounds even better to me

@billmcspadden-riscv
Copy link
Collaborator

billmcspadden-riscv commented Jan 9, 2025 via email

Move the softfloat library to a dependencies directory. In future we can add GMP there too to reduce the number of external dependencies needed and to support static linking.

The directory was renamed from `SoftFloat-3e` to `berkeley-softfloat-3` because that's how the latest version is named.

It hasn't been upgraded in this commit to make it simpler to review and help Git track history. A future commit will upgrade it.
This is a draft of a CMake build system. It doesn't yet include RVFI, JSON docs, formal stuff, etc.
@Timmmm
Copy link
Collaborator Author

Timmmm commented Jan 10, 2025

I've rebased it, removed the c_emulator rename and the softfloat update (we can do that later), and added RVFI support. I also updated the CI scripts.

I'm not sure I'm much of a fan of having two build systems during a transition. Verilator has exactly this - an old ./configure && make and an "experimental" CMake build system, and IMO it is quite confusing for users, and probably annoying for developers.

I reckon I can add the other targets without too much trouble, assuming they still work anyway! They aren't tested by CI and are presumably very rarely used.

@@ -1,6 +1,6 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: '^(prover_snapshots)|(generated_definitions)|(c_emulator/SoftFloat-3e)'
exclude: '^(prover_snapshots)|(generated_definitions)|(dependencies/softfloat/berkeley-softfloat-3)'
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we shouldn't run the checks on any dependencies? How about this:

Suggested change
exclude: '^(prover_snapshots)|(generated_definitions)|(dependencies/softfloat/berkeley-softfloat-3)'
exclude: '^(prover_snapshots)|(generated_definitions)|(dependencies)'

@@ -1,428 +0,0 @@
# Select architecture: RV32 or RV64.
ARCH ?= RV64
Copy link
Collaborator

Choose a reason for hiding this comment

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

Need to keep makefile for now for the prover stuff?

}

test_build make ARCH=RV32 c_emulator/riscv_sim_RV32
test_build make ARCH=RV64 c_emulator/riscv_sim_RV64
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this documented anywhere as a sensible script to use? If so we could just update it to use CMake?

Comment on lines -184 to -211
ifneq (,$(COVERAGE))
C_FLAGS += --coverage -O1
SAIL_FLAGS += -Oconstant_fold
else
C_FLAGS += -O3 -flto=auto
endif

ifneq (,$(SAILCOV))
ALL_BRANCHES = generated_definitions/c/all_branches
C_FLAGS += -DSAILCOV
SAIL_FLAGS += -c_coverage $(ALL_BRANCHES) -c_include sail_coverage.h
C_LIBS += $(SAIL_LIB_DIR)/coverage/libsail_coverage.a -lm -lpthread -ldl
endif

# Optionally link C_LIBS statically. Unlike -static this will not
# link glibc statically which is generally a bad idea.
ifneq (,$(STATIC))
UNAME_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
ifeq ($(UNAME_S),Darwin)
# Unfortunately the Mac linker does not support -Bstatic.
GMP_LIBS = $(shell pkg-config --variable=libdir gmp)/libgmp.a
C_LIBS_WRAPPED = $(C_LIBS)
else
C_LIBS_WRAPPED = -Wl,--push-state -Wl,-Bstatic $(C_LIBS) -Wl,--pop-state
endif
else
C_LIBS_WRAPPED = $(C_LIBS)
endif
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe we have lost support for these options. I've used the sailcov option before, but not the other ones.

Comment on lines -342 to -344
riscv_hol: generated_definitions/hol4/$(ARCH)/riscvScript.sml
riscv_hol_build: generated_definitions/hol4/$(ARCH)/riscvTheory.uo
.PHONY: riscv_hol riscv_hol_build
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the hol target still working? If so do we need to port it over to cmake?

riscv_softfloat.h
)

foreach (arch IN ITEMS "rv32" "rv32d" "rv64" "rv64f" "rv32_rvfi" "rv32d_rvfi" "rv64_rvfi" "rv64f_rvfi")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we use variants here as well to make it easier to add the other targets in the future?

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Overall I still think this is a great change. A few things that were supported are no longer there.

I wonder if we should keep the Makefile for now and add something like the following to the top:

ifndef I_REALLY_NEED_TO_USE_MAKE
$(error The Makefile build system is deprecated, please use CMake instead. If you are using a target that does not exist there yet, please file and issue and re-run make with I_REALLY_NEED_TO_USE_MAKE=1 until this has been fixed)
endif

@arichardson
Copy link
Collaborator

I've rebased it, removed the c_emulator rename and the softfloat update (we can do that later), and added RVFI support. I also updated the CI scripts.

I'm not sure I'm much of a fan of having two build systems during a transition. Verilator has exactly this - an old ./configure && make and an "experimental" CMake build system, and IMO it is quite confusing for users, and probably annoying for developers.

I reckon I can add the other targets without too much trouble, assuming they still work anyway! They aren't tested by CI and are presumably very rarely used.

I agree that having multiple build systems is annoying and confusing. What do you think of my suggestion to add a (opt-out) error to the makefile to point people towards CMake.

We should probably also update the README.

message(FATAL_ERROR "Sail not found. See README.md for installation instructions.")
endif()

set(DEFAULT_ARCHITECTURES "rv32;rv64" CACHE STRING "Architectures to build by default (rv32|rv64|rv32d|rv64f)(_rvfi)? " )
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's not clear to me on first read what these things mean. My initial interpretation was:
rv32: no float
rv64: no float
rv32d: FLEN=64
rv64f: FLEN=32

But then that's odd because FLEN=64 is a sensible configuration for RV64 (more so than FLEN=32, even), and of course that's not actually what's going on, there's a default non-zero FLEN and then the suffixed ones are overrides. But those names are confusing and weird.

On top of that, this is a behavioural change. The current Makefile build always defaults to FLEN=64 even for RV32, but you've changed that default to be FLEN=32.

@arichardson
Copy link
Collaborator

Once this lands, I am happy to submit some follow-up improvements to support static builds and builds that build GMP from source as part of the build process to avoid any system dependencies.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 10, 2025

I've rebased it, removed the c_emulator rename and the softfloat update (we can do that later), and added RVFI support. I also updated the CI scripts.
I'm not sure I'm much of a fan of having two build systems during a transition. Verilator has exactly this - an old ./configure && make and an "experimental" CMake build system, and IMO it is quite confusing for users, and probably annoying for developers.
I reckon I can add the other targets without too much trouble, assuming they still work anyway! They aren't tested by CI and are presumably very rarely used.

I agree that having multiple build systems is annoying and confusing. What do you think of my suggestion to add a (opt-out) error to the makefile to point people towards CMake.

We should probably also update the README.

I mean, if the Makefile is needed in some cases then it shouldn't be an error to use it. And if it's not needed then it can be deleted.

It's not confusing at all to have both, provided the CMake one is clearly labelled as experimental and in-progress. What's confusing is when there are two documented ways of building (or one documented but the other one isn't clearly labelled as "don't use yet unless you really want to").

@arichardson
Copy link
Collaborator

I've rebased it, removed the c_emulator rename and the softfloat update (we can do that later), and added RVFI support. I also updated the CI scripts.
I'm not sure I'm much of a fan of having two build systems during a transition. Verilator has exactly this - an old ./configure && make and an "experimental" CMake build system, and IMO it is quite confusing for users, and probably annoying for developers.
I reckon I can add the other targets without too much trouble, assuming they still work anyway! They aren't tested by CI and are presumably very rarely used.

I agree that having multiple build systems is annoying and confusing. What do you think of my suggestion to add a (opt-out) error to the makefile to point people towards CMake.
We should probably also update the README.

I mean, if the Makefile is needed in some cases then it shouldn't be an error to use it. And if it's not needed then it can be deleted.

It's not confusing at all to have both, provided the CMake one is clearly labelled as experimental and in-progress. What's confusing is when there are two documented ways of building (or one documented but the other one isn't clearly labelled as "don't use yet unless you really want to").

I agree it shouldn't be an error when it's needed. I was just suggesting making it an error that you can override to find out if anyone is using the targets that don't exist in the CMkae world yet.

If we just add a deprecation warning or keep the makefile around unchanged no one is going to report it until it becomes an error.

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.

5 participants