Clarionos/clarion

Improving C++ builds

Closed this issue · 9 comments

Please ignore if you're not into longform rants on building C++ projects in continuous integration. If you're into that kind of thing, then this is going to be your kind of github issue.

I want to boot to a polyglot development environment. When do I want it? Now! How much time do I want to spend configuring my development environment? Zero.

That's part of what I'm building with SOS. I'll do all the configuration ones so that others never need to do it again.

Recently I was having issue with RocksDB uniqueness constraints in blurt.

We had been using Conan to build it and we were stuck on the version of rocksdb that Conan was shipping and that sucks. It was also hard to tell Conan, "build facebook/rocksdb from master, using your recipe"

Instead, build the entire stack and its dependencies from source every time and use ccache.

If ccache and clang are present, you shouldn't need anything else to build a Clarion or a blurt or whatever.

And on at least one computer, I've got that working. There is some more cmake hackery to finish here, but please hear me out....

So like most changes to these library's are not breaking changes and downstream work benefits from using the very latest versions of these library's. Therefore, I am suggesting that the convention should be to use external libraries like boost or wasi or rocksdb or whatever....

in cmake, in a very simple fashion:

https://cmake.org/cmake/help/latest/module/ExternalProject.html

include(ExternalProject)
ExternalProject_Add(foobar
  GIT_REPOSITORY    git@github.com:FooCo/FooBar.git
  GIT_TAG           master 
# or just do not specify a tag but I am not sure that works
)

Then in the master branch, always take the master branches of other projects, so that the master branch is always up-to-date. When I say up-to-date, I also mean that it's libraries and things are up-to-date as well.

When it's time to cut a release, use fixed versions for all of the libraries.

Check it out, I'm pretty sure that if we create a wrapper for this make that makes it easy, say like a wrapper for the externalProject bit and a wrapper for importing the libraries of external projects which is currently a little bit of a pain in the butt, I believe that is the actual solution to C++ package management, NOT conan.

If we practiced this discipline, we also get easy builds for any platform, and our CIA system will be able to tell us if we fall out of compliance on that, instantly. Additionally, because we will be specifying git tags for the external projects when we make releases, releases are a fixed, static thing, as they should be.

I'm pretty proud of figuring out the solution but I don't know if it's actually right.....

so if folks could let me know what they think I'd really appreciate it, particularly the person who taught me all the stuff by releasing his source code, @bytemaster

;)

See the way we're currently doing cicd at https://github.com/eoscommunity/Eden

Screen Shot 2021-05-10 at 11 36 13 AM

I'd like to fix the part where we end up writing code to match the versions of libs shipped in "the latest ubuntu"

Example: I reckon that the build system for clarion (eden too I guess) should also build wasi.

As for node, 16 has been released, so we should be using that.

Arch linux ships with fresh everything, we can trust it for:

  • Clang
  • node
  • git
  • make
  • go
  • rust

....all that other stuff. At the end of the day I ended up working in a very, very polyglot manner and a very, very multiarchitecture manner.

Current fave dev machine is an m1

often deploy to both raspi and graviton

still have a 32 core threadripper in case need raw power.

PS:

I developed this idea, just getting blurt going on my M1 MBP:

Screen Shot 2021-05-10 at 11 42 13 AM

.... it even stands back up after suspending. This machine will be my witness in a moment.

I think that it would make a lot of sense to change the flow of clarion/bitshares/eos/eden (or whatever c++ really) development so that it is not so dependent on the operating system.

kinda like:

https://github.com/FISCO-BCOS/FISCO-BCOS/blob/master/cmake/ProjectRocksDB.cmake

include(ExternalProject)

if (APPLE)
    set(SED_CMMAND sed -i .bkp)
    set(COMPILER_FLAGS "-Wno-defaulted-function-deleted -Wno-shadow")
else()
    set(SED_CMMAND sed -i)
    set(COMPILER_FLAGS "")
endif()

ExternalProject_Add(rocksdb
    PREFIX ${CMAKE_SOURCE_DIR}/deps
    DOWNLOAD_NAME rocksdb_6.0.2.tar.gz
    DOWNLOAD_NO_PROGRESS 1
    URL https://codeload.github.com/facebook/rocksdb/tar.gz/v6.0.2
    URL_HASH SHA256=89e0832f1fb00ac240a9438d4bbdae37dd3e52f7c15c3f646dc26887da16f342
    # remove dynamic lib and gtest. NOTE: sed line number should update once RocksDB upgrade
    PATCH_COMMAND ${SED_CMMAND} "s#-march=native#${MARCH_TYPE} ${COMPILER_FLAGS} #g" CMakeLists.txt COMMAND ${SED_CMMAND} "464d" CMakeLists.txt COMMAND ${SED_CMMAND} "739,749d" CMakeLists.txt COMMAND ${SED_CMMAND} "805,813d" CMakeLists.txt COMMAND ${SED_CMMAND} "s#-Werror##g" CMakeLists.txt
    BUILD_IN_SOURCE 1
    CMAKE_COMMAND ${CMAKE_COMMAND}
    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
    -DCMAKE_POSITION_INDEPENDENT_CODE=ON
    ${_only_release_configuration}
    -DWITH_LZ4=OFF
    -DWITH_SNAPPY=ON
    -DWITH_GFLAGS=OFF
    -DWITH_TESTS=OFF
    -DWITH_TOOLS=OFF
    -DBUILD_SHARED_LIBS=OFF
    -DUSE_RTTI=ON
    -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} ${MARCH_TYPE}
    -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} ${MARCH_TYPE}
    -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
    -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
    INSTALL_COMMAND ""
    LOG_CONFIGURE 1
    LOG_DOWNLOAD 1
    LOG_UPDATE 1
    LOG_BUILD 1
    LOG_INSTALL 1
    BUILD_BYPRODUCTS <SOURCE_DIR>/librocksdb.a
)

ExternalProject_Get_Property(rocksdb SOURCE_DIR)
add_library(RocksDB STATIC IMPORTED GLOBAL)

set(ROCKSDB_INCLUDE_DIR ${SOURCE_DIR}/include/)
set(ROCKSDB_LIBRARY ${SOURCE_DIR}/librocksdb.a)
file(MAKE_DIRECTORY ${ROCKSDB_INCLUDE_DIR})  # Must exist.

set_property(TARGET RocksDB PROPERTY IMPORTED_LOCATION ${ROCKSDB_LIBRARY})
set_property(TARGET RocksDB PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ROCKSDB_INCLUDE_DIR})
set_property(TARGET RocksDB PROPERTY INTERFACE_LINK_LIBRARIES Snappy)

add_dependencies(rocksdb Snappy)
add_dependencies(RocksDB rocksdb)
unset(SOURCE_DIR)

I'll send over a link and eventually a patch, when I think that this feels right.

What I am proposing is:

  • For clarion, wasi-sdk should be built like this.
  • master branch should always refer to wasi-sdk's master branch
  • releases should specify a commit hash

The goal is:

  • conan-style ease of use
  • totally native, zero configuration support for:
    • mac (arm64 and amd64)
    • linux (arm64, amd64 and eventually riscv64)
    • maybe windows but yuck

In the other repo, we get rocksdb without having to sed

oh then I surely didn't look close enough. Thank you @tbfleming

Initally I only looked at the workflows. The CMake stuff is great!

Thank you.

I guess you're currently using git submodules then applying cmake to it?

Closing due to learning a better way from @tbfleming

I guess you're currently using git submodules then applying cmake to it?

Yes, except for boost, which is composed of a large number of submodules (poor clone performance). Right now:

  • Native builds use the platform-provided boost (not ideal)
  • wasm builds fetch a boost .zip and use custom CMakeFile rules

Thank you for teaching.