Skip to content

Conversation

@jmarrec
Copy link
Collaborator

@jmarrec jmarrec commented Apr 7, 2025

Pull request overview

I am extremely unhappy with what I came up with, but that's the result of a day of hitting the same wall.

I'm not even 100% sure this fixes all corner cases yet.

We ought to remove the embedded filesystem.

Pull Request Author

  • Model API Changes / Additions
  • Any new or modified fields have been implemented in the EnergyPlus ForwardTranslator (and ReverseTranslator as appropriate)
  • Model API methods are tested (in src/model/test)
  • EnergyPlus ForwardTranslator Tests (in src/energyplus/Test)
  • If a new object or method, added a test in NREL/OpenStudio-resources: Add Link
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • Verified that C# bindings built fine on Windows, partial classes used as needed, etc.
  • All new and existing tests passes
  • If methods have been deprecated, update rest of code to use the new methods

Labels:

  • If change to an IDD file, add the label IDDChange
  • If breaking existing API, add the label APIChange
  • If deemed ready, add label Pull Request - Ready for CI so that CI builds your PR

Review Checklist

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • Code Style, strip trailing whitespace, etc.
  • All related changes have been implemented: model changes, model tests, FT changes, FT tests, VersionTranslation, OS App
  • Labeling is ok
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified

@jmarrec jmarrec added component - CLI Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. labels Apr 7, 2025
@jmarrec jmarrec requested a review from kbenne April 7, 2025 15:52
@jmarrec jmarrec self-assigned this Apr 7, 2025
jmarrec added 4 commits April 8, 2025 14:06
…plate BEFORE RbConfig::expand_path is called when it's instantiated

cat /home/julien/.conan2/p/rubydc7aa974e6bfc/p/lib/ruby/3.2.0/x86_64-linux/rbconfig.rb

```ruby
# encoding: ascii-8bit
# frozen-string-literal: false
#
# The module storing Ruby interpreter configurations on building.
#
# This file was created by mkconfig.rb when ruby was built.  It contains
# build information for ruby which is used e.g. by mkmf to build
# compatible native extensions.  Any changes made to this file will be
# lost the next time ruby is built.

module RbConfig
  RUBY_VERSION.start_with?("3.2.") or
    raise "ruby lib version (3.2.2) doesn't match executable version (#{RUBY_VERSION})"

  # Ruby installed directory.
  TOPDIR = File.dirname(__FILE__).chomp!("/lib/ruby/3.2.0/x86_64-linux")
  # DESTDIR on make install.
  DESTDIR = '' unless defined? DESTDIR
  # The hash configurations stored.
  CONFIG = {}
  CONFIG["DESTDIR"] = DESTDIR
  CONFIG["MAJOR"] = "3"
  CONFIG["MINOR"] = "2"
  CONFIG["TEENY"] = "2"
  CONFIG["PATCHLEVEL"] = "53"
  CONFIG["INSTALL"] = '/usr/bin/install -c'
  CONFIG["EXEEXT"] = ""
  CONFIG["prefix"] = (TOPDIR || DESTDIR + "/")
  CONFIG["ruby_install_name"] = "$(RUBY_BASE_NAME)"
  CONFIG["RUBY_INSTALL_NAME"] = "$(RUBY_BASE_NAME)"
  CONFIG["RUBY_SO_NAME"] = "$(RUBY_BASE_NAME)"
  CONFIG["exec"] = "exec"
  CONFIG["ruby_pc"] = "ruby-3.2.pc"
  CONFIG["CC_WRAPPER"] = ""
  CONFIG["PACKAGE"] = "ruby"
  CONFIG["BUILTIN_TRANSSRCS"] = " enc/trans/newline.c"
  CONFIG["MKMF_VERBOSE"] = "1"
  CONFIG["MANTYPE"] = "doc"
  CONFIG["vendorarchhdrdir"] = "$(vendorhdrdir)/$(sitearch)"
  CONFIG["sitearchhdrdir"] = "$(sitehdrdir)/$(sitearch)"
  CONFIG["rubyarchhdrdir"] = "$(rubyhdrdir)/$(arch)"
  CONFIG["vendorhdrdir"] = "$(rubyhdrdir)/vendor_ruby"
  CONFIG["sitehdrdir"] = "$(rubyhdrdir)/site_ruby"
  CONFIG["rubyhdrdir"] = "$(includedir)/$(RUBY_VERSION_NAME)"
  CONFIG["RUBY_SEARCH_PATH"] = ""
  CONFIG["UNIVERSAL_INTS"] = ""
  CONFIG["UNIVERSAL_ARCHNAMES"] = ""
  CONFIG["configure_args"] = " '--disable-shared' '--enable-static' '--prefix=/' '--bindir=$${prefix}/bin' '--sbindir=$${prefix}/bin' '--libdir=$${prefix}/lib' '--includedir=$${prefix}/include' '--oldincludedir=$${prefix}/include' '--disable-install-doc' '--with-static-linked-ext' '--enable-load-relative' '--enable-debug-env' '--with-zlib-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p' '--with-openssl-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p' '--with-libffi-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p' '--with-libyaml-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p' '--with-readline-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p' '--with-gmp-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p' '--with-opt-dir=/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p:/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p:/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p:/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p:/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p:/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p' '--disable-jit-support' '--enable-mkmf-verbose' 'CFLAGS= -m64 -fPIC -g' 'LDFLAGS= -m64' 'CPPFLAGS=' 'CXXFLAGS= -m64 -fPIC -g'"
  CONFIG["CONFIGURE"] = "configure"
  CONFIG["vendorarchdir"] = "$(vendorlibdir)/$(sitearch)"
  CONFIG["vendorlibdir"] = "$(vendordir)/$(ruby_version)"
  CONFIG["vendordir"] = "$(rubylibprefix)/vendor_ruby"
  CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)"
  CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)"
  CONFIG["sitedir"] = "$(rubylibprefix)/site_ruby"
  CONFIG["rubyarchdir"] = "$(rubylibdir)/$(arch)"
  CONFIG["rubylibdir"] = "$(rubylibprefix)/$(ruby_version)"
  CONFIG["ruby_version"] = "3.2.0"
  CONFIG["sitearch"] = "$(arch)"
  CONFIG["arch"] = "x86_64-linux"
  CONFIG["sitearchincludedir"] = "$(includedir)/$(sitearch)"
  CONFIG["archincludedir"] = "$(includedir)/$(arch)"
  CONFIG["sitearchlibdir"] = "$(libdir)/$(sitearch)"
  CONFIG["archlibdir"] = "$(libdir)/$(arch)"
  CONFIG["libdirname"] = "libdir"
  CONFIG["RUBY_EXEC_PREFIX"] = ""
  CONFIG["RUBY_LIB_VERSION"] = ""
  CONFIG["RUBY_LIB_VERSION_STYLE"] = "3\t/* full */"
  CONFIG["RI_BASE_NAME"] = "ri"
  CONFIG["ridir"] = "$(datarootdir)/$(RI_BASE_NAME)"
  CONFIG["rubysitearchprefix"] = "$(rubylibprefix)/$(sitearch)"
  CONFIG["rubyarchprefix"] = "$(rubylibprefix)/$(arch)"
  CONFIG["MAKEFILES"] = "Makefile GNUmakefile"
  CONFIG["PLATFORM_DIR"] = ""
  CONFIG["COROUTINE_TYPE"] = "amd64"
  CONFIG["THREAD_MODEL"] = "pthread"
  CONFIG["SYMBOL_PREFIX"] = ""
  CONFIG["EXPORT_PREFIX"] = ""
  CONFIG["COMMON_HEADERS"] = ""
  CONFIG["COMMON_MACROS"] = ""
  CONFIG["COMMON_LIBS"] = ""
  CONFIG["MAINLIBS"] = "-lz -lrt -lrt -lgmp -ldl -lcrypt -lm -lpthread "
  CONFIG["ENABLE_SHARED"] = "no"
  CONFIG["DLDSHARED"] = "$(CC) -shared"
  CONFIG["DLDLIBS"] = "-lc"
  CONFIG["SOLIBS"] = "$(MAINLIBS)"
  CONFIG["LIBRUBYARG_SHARED"] = "-Wl,-rpath,$(libdir) "
  CONFIG["LIBRUBYARG_STATIC"] = "-Wl,-rpath,$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS)"
  CONFIG["LIBRUBYARG"] = "$(LIBRUBYARG_STATIC)"
  CONFIG["LIBRUBY"] = "$(LIBRUBY_A)"
  CONFIG["LIBRUBY_ALIASES"] = "lib$(RUBY_SO_NAME).$(SOEXT)"
  CONFIG["LIBRUBY_SONAME"] = "lib$(RUBY_SO_NAME).$(SOEXT).$(RUBY_API_VERSION)"
  CONFIG["LIBRUBY_SO"] = "lib$(RUBY_SO_NAME).$(SOEXT).$(RUBY_PROGRAM_VERSION)"
  CONFIG["LIBRUBY_A"] = "lib$(RUBY_SO_NAME)-static.a"
  CONFIG["RUBYW_INSTALL_NAME"] = ""
  CONFIG["rubyw_install_name"] = ""
  CONFIG["EXTDLDFLAGS"] = ""
  CONFIG["EXTLDFLAGS"] = ""
  CONFIG["strict_warnflags"] = ""
  CONFIG["warnflags"] = "-Wall -Wextra -Wdeprecated-declarations -Wdiv-by-zero -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wold-style-definition -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Wundef"
  CONFIG["debugflags"] = "-ggdb3"
  CONFIG["optflags"] = "-O3 -fno-fast-math"
  CONFIG["NULLCMD"] = ":"
  CONFIG["ENABLE_DEBUG_ENV"] = "yes"
  CONFIG["DLNOBJ"] = "dln.o"
  CONFIG["INSTALL_STATIC_LIBRARY"] = "yes"
  CONFIG["YJIT_OBJ"] = ""
  CONFIG["YJIT_LIBS"] = ""
  CONFIG["CARGO_BUILD_ARGS"] = ""
  CONFIG["YJIT_SUPPORT"] = "no"
  CONFIG["CARGO"] = ""
  CONFIG["RUSTC"] = "rustc"
  CONFIG["MJIT_SUPPORT"] = "no"
  CONFIG["EXECUTABLE_EXTS"] = ""
  CONFIG["ARCHFILE"] = ""
  CONFIG["LIBRUBY_RELATIVE"] = "yes"
  CONFIG["EXTOUT"] = ".ext"
  CONFIG["PREP"] = "miniruby$(EXEEXT)"
  CONFIG["CROSS_COMPILING"] = "no"
  CONFIG["TEST_RUNNABLE"] = "yes"
  CONFIG["rubylibprefix"] = "$(libdir)/$(RUBY_BASE_NAME)"
  CONFIG["setup"] = "Setup"
  CONFIG["SOEXT"] = "so"
  CONFIG["TRY_LINK"] = ""
  CONFIG["PRELOADENV"] = "LD_PRELOAD"
  CONFIG["LIBPATHENV"] = "LD_LIBRARY_PATH"
  CONFIG["RPATHFLAG"] = " -Wl,-rpath,%1$-s"
  CONFIG["LIBPATHFLAG"] = " -L%1$-s"
  CONFIG["LINK_SO"] = ""
  CONFIG["ADDITIONAL_DLDFLAGS"] = ""
  CONFIG["ENCSTATIC"] = "static"
  CONFIG["EXTSTATIC"] = "static"
  CONFIG["ASMEXT"] = "S"
  CONFIG["LIBEXT"] = "a"
  CONFIG["DLEXT"] = "so"
  CONFIG["LDSHAREDXX"] = "$(CXX) -shared"
  CONFIG["LDSHARED"] = "$(CC) -shared"
  CONFIG["CCDLFLAGS"] = ""
  CONFIG["STATIC"] = ""
  CONFIG["ARCH_FLAG"] = "-m64"
  CONFIG["DLDFLAGS"] = " -m64 -Wl,--compress-debug-sections=zlib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib"
  CONFIG["ALLOCA"] = ""
  CONFIG["EGREP"] = "/usr/bin/grep -E"
  CONFIG["GREP"] = "/usr/bin/grep"
  CONFIG["dsymutil"] = ""
  CONFIG["codesign"] = ""
  CONFIG["cleanlibs"] = ""
  CONFIG["POSTLINK"] = ":"
  CONFIG["WERRORFLAG"] = "-Werror"
  CONFIG["RUBY_DEVEL"] = ""
  CONFIG["CHDIR"] = "cd -P"
  CONFIG["RMALL"] = "rm -fr"
  CONFIG["RMDIRS"] = "rmdir --ignore-fail-on-non-empty -p"
  CONFIG["RMDIR"] = "rmdir --ignore-fail-on-non-empty"
  CONFIG["CP"] = "cp"
  CONFIG["RM"] = "rm -f"
  CONFIG["PKG_CONFIG"] = "/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/pkgcod896fda73101e/p/bin/pkgconf"
  CONFIG["DOXYGEN"] = ""
  CONFIG["DOT"] = ""
  CONFIG["MKDIR_P"] = "/usr/bin/mkdir -p"
  CONFIG["INSTALL_DATA"] = "$(INSTALL) -m 644"
  CONFIG["INSTALL_SCRIPT"] = "$(INSTALL)"
  CONFIG["INSTALL_PROGRAM"] = "$(INSTALL)"
  CONFIG["SET_MAKE"] = ""
  CONFIG["LN_S"] = "ln -s"
  CONFIG["DLLWRAP"] = ""
  CONFIG["WINDRES"] = ""
  CONFIG["ASFLAGS"] = ""
  CONFIG["ARAPPENDFLAGS"] = "rD "
  CONFIG["ARDELETEFLAGS"] = "dD "
  CONFIG["ARFLAGS"] = "rcD "
  CONFIG["try_header"] = ""
  CONFIG["CC_VERSION_MESSAGE"] = "gcc (Ubuntu 13.1.0-8ubuntu1~22.04) 13.1.0\nCopyright (C) 2023 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
  CONFIG["CC_VERSION"] = "$(CC) --version"
  CONFIG["MJIT_CC"] = "/usr/bin/gcc"
  CONFIG["CSRCFLAG"] = ""
  CONFIG["COUTFLAG"] = "-o "
  CONFIG["OUTFLAG"] = "-o "
  CONFIG["CPPOUTFILE"] = "-o conftest.i"
  CONFIG["GNU_LD"] = "yes"
  CONFIG["GCC"] = "yes"
  CONFIG["CPP"] = "$(CC) -E"
  CONFIG["CXXFLAGS"] = " -fPIC -g"
  CONFIG["OBJEXT"] = "o"
  CONFIG["CPPFLAGS"] = "-I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p/include -I/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/include $(DEFS) $(cppflags)"
  CONFIG["LDFLAGS"] = "-L. -fstack-protector-strong -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/zlib8b6dc70ac578e/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/opens03d4769e65868/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/b/libff3836ee26e9203/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/libyae4e647619ca18/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/readl070d86bde5656/p/lib -L/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib  -Wl,-rpath,/home/runner/work/conan-recipes/conan-recipes/conan-cache/.conan2/p/gmpfd399f3cf2e2a/p/lib -rdynamic -Wl,-export-dynamic"
  CONFIG["CFLAGS"] = " -fPIC -g"
  CONFIG["STRIP"] = "strip -S -x"
  CONFIG["RANLIB"] = "gcc-ranlib"
  CONFIG["OBJDUMP"] = "objdump"
  CONFIG["OBJCOPY"] = ":"
  CONFIG["NM"] = "gcc-nm"
  CONFIG["LD"] = "ld"
  CONFIG["CXX"] = "g++"
  CONFIG["AS"] = "as"
  CONFIG["AR"] = "gcc-ar"
  CONFIG["CC"] = "gcc"
  CONFIG["wasmoptflags"] = ""
  CONFIG["WASMOPT"] = ""
  CONFIG["target_os"] = "linux"
  CONFIG["target_vendor"] = "pc"
  CONFIG["target_cpu"] = "x86_64"
  CONFIG["target"] = "$(target_cpu)-$(target_vendor)-$(target_os)"
  CONFIG["host_os"] = "$(target_os)"
  CONFIG["host_vendor"] = "$(target_vendor)"
  CONFIG["host_cpu"] = "$(target_cpu)"
  CONFIG["host"] = "$(target)"
  CONFIG["build_os"] = "linux-gnu"
  CONFIG["build_vendor"] = "pc"
  CONFIG["build_cpu"] = "x86_64"
  CONFIG["build"] = "x86_64-pc-linux-gnu"
  CONFIG["RUBY_VERSION_NAME"] = "$(RUBY_BASE_NAME)-$(ruby_version)"
  CONFIG["RUBYW_BASE_NAME"] = "rubyw"
  CONFIG["RUBY_BASE_NAME"] = "ruby"
  CONFIG["RUBY_PROGRAM_VERSION"] = "$(MAJOR).$(MINOR).$(TEENY)"
  CONFIG["RUBY_API_VERSION"] = "$(MAJOR).$(MINOR)"
  CONFIG["HAVE_GIT"] = "yes"
  CONFIG["GIT"] = "git"
  CONFIG["cxxflags"] = ""
  CONFIG["cppflags"] = ""
  CONFIG["cflags"] = "$(optflags) $(debugflags) $(warnflags)"
  CONFIG["MAKEDIRS"] = "/usr/bin/mkdir -p"
  CONFIG["target_alias"] = ""
  CONFIG["host_alias"] = "$(target_alias)"
  CONFIG["build_alias"] = ""
  CONFIG["LIBS"] = "-lm -lpthread "
  CONFIG["ECHO_T"] = ""
  CONFIG["ECHO_N"] = "-n"
  CONFIG["ECHO_C"] = ""
  CONFIG["DEFS"] = ""
  CONFIG["mandir"] = "$(datarootdir)/man"
  CONFIG["localedir"] = "$(datarootdir)/locale"
  CONFIG["libdir"] = "$(prefix)/lib"
  CONFIG["psdir"] = "$(docdir)"
  CONFIG["pdfdir"] = "$(docdir)"
  CONFIG["dvidir"] = "$(docdir)"
  CONFIG["htmldir"] = "$(docdir)"
  CONFIG["infodir"] = "$(datarootdir)/info"
  CONFIG["docdir"] = "$(datarootdir)/doc/$(PACKAGE)"
  CONFIG["oldincludedir"] = "$(prefix)/include"
  CONFIG["includedir"] = "$(prefix)/include"
  CONFIG["runstatedir"] = "$(localstatedir)/run"
  CONFIG["localstatedir"] = "$(prefix)/var"
  CONFIG["sharedstatedir"] = "$(prefix)/com"
  CONFIG["sysconfdir"] = "$(prefix)/etc"
  CONFIG["datadir"] = "$(datarootdir)"
  CONFIG["datarootdir"] = "$(prefix)/share"
  CONFIG["libexecdir"] = "$(exec_prefix)/libexec"
  CONFIG["sbindir"] = "$(prefix)/bin"
  CONFIG["bindir"] = "$(prefix)/bin"
  CONFIG["exec_prefix"] = "$(prefix)"
  CONFIG["PACKAGE_URL"] = ""
  CONFIG["PACKAGE_BUGREPORT"] = ""
  CONFIG["PACKAGE_STRING"] = ""
  CONFIG["PACKAGE_VERSION"] = ""
  CONFIG["PACKAGE_TARNAME"] = ""
  CONFIG["PACKAGE_NAME"] = ""
  CONFIG["PATH_SEPARATOR"] = ":"
  CONFIG["SHELL"] = "/bin/bash"
  CONFIG["UNICODE_VERSION"] = "15.0.0"
  CONFIG["UNICODE_EMOJI_VERSION"] = "15.0"
  CONFIG["platform"] = "$(arch)"
  CONFIG["archdir"] = "$(rubyarchdir)"
  CONFIG["topdir"] = File.dirname(__FILE__)
  # Almost same with CONFIG. MAKEFILE_CONFIG has other variable
  # reference like below.
  #
  #   MAKEFILE_CONFIG["bindir"] = "$(exec_prefix)/bin"
  #
  # The values of this constant is used for creating Makefile.
  #
  #   require 'rbconfig'
  #
  #   print <<-END_OF_MAKEFILE
  #   prefix = #{RbConfig::MAKEFILE_CONFIG['prefix']}
  #   exec_prefix = #{RbConfig::MAKEFILE_CONFIG['exec_prefix']}
  #   bindir = #{RbConfig::MAKEFILE_CONFIG['bindir']}
  #   END_OF_MAKEFILE
  #
  #   => prefix = /usr/local
  #      exec_prefix = $(prefix)
  #      bindir = $(exec_prefix)/bin  MAKEFILE_CONFIG = {}
  #
  # RbConfig.expand is used for resolving references like above in rbconfig.
  #
  #   require 'rbconfig'
  #   p RbConfig.expand(RbConfig::MAKEFILE_CONFIG["bindir"])
  #   # => "/usr/local/bin"
  MAKEFILE_CONFIG = {}
  CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup}

  # call-seq:
  #
  #   RbConfig.expand(val)         -> string
  #   RbConfig.expand(val, config) -> string
  #
  # expands variable with given +val+ value.
  #
  #   RbConfig.expand("$(bindir)") # => /home/foobar/all-ruby/ruby19x/bin
  def RbConfig::expand(val, config = CONFIG)
    newval = val.gsub(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) {
      var = $&
      if !(v = $1 || $2)
	'$'
      elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]]
	pat, sub = $1, $2
	config[v] = false
	config[v] = RbConfig::expand(key, config)
	key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat
	key
      else
	var
      end
    }
    val.replace(newval) unless newval == val
    val
  end
  CONFIG.each_value do |val|
    RbConfig::expand(val)
  end

  # call-seq:
  #
  #   RbConfig.fire_update!(key, val)               -> array
  #   RbConfig.fire_update!(key, val, mkconf, conf) -> array
  #
  # updates +key+ in +mkconf+ with +val+, and all values depending on
  # the +key+ in +mkconf+.
  #
  #   RbConfig::MAKEFILE_CONFIG.values_at("CC", "LDSHARED") # => ["gcc", "$(CC) -shared"]
  #   RbConfig::CONFIG.values_at("CC", "LDSHARED")          # => ["gcc", "gcc -shared"]
  #   RbConfig.fire_update!("CC", "gcc-8")                  # => ["CC", "LDSHARED"]
  #   RbConfig::MAKEFILE_CONFIG.values_at("CC", "LDSHARED") # => ["gcc-8", "$(CC) -shared"]
  #   RbConfig::CONFIG.values_at("CC", "LDSHARED")          # => ["gcc-8", "gcc-8 -shared"]
  #
  # returns updated keys list, or +nil+ if nothing changed.
  def RbConfig.fire_update!(key, val, mkconf = MAKEFILE_CONFIG, conf = CONFIG) # :nodoc:
    return if mkconf[key] == val
    mkconf[key] = val
    keys = [key]
    deps = []
    begin
      re = Regexp.new("\\$\\((?:%1$s)\\)|\\$\\{(?:%1$s)\\}" % keys.join('|'))
      deps |= keys
      keys.clear
      mkconf.each {|k,v| keys << k if re =~ v}
    end until keys.empty?
    deps.each {|k| conf[k] = mkconf[k].dup}
    deps.each {|k| expand(conf[k])}
    deps
  end

  # call-seq:
  #
  #   RbConfig.ruby -> path
  #
  # returns the absolute pathname of the ruby command.
  def RbConfig.ruby
    File.join(
      RbConfig::CONFIG["bindir"],
      RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
    )
  end
end
CROSS_COMPILING = nil unless defined? CROSS_COMPILING
```
Copy link
Collaborator Author

@jmarrec jmarrec left a comment

Choose a reason for hiding this comment

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

Review for #5388

# Filter out dependencies with native extensions that we already have embedded in the CLI and that satisfy the requirements
locked_specs = Bundler.definition.instance_variable_get(:@locked_specs)
extra_load_paths = []
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Store

Comment on lines +992 to +1032
locked_spec = locked_specs.select{|locked_spec| locked_spec.name == spec.name}.first
$logger.debug("Removing native gem #{spec.name} from Bundler locked_specs (version #{locked_spec.version}), using the embedded dependency (CLI one has version #{spec.version})")
$logger.trace("Gems having #{spec.name} as a dependency: #{dep_to_requirements}")
locked_spec.dependencies.each do |dep|
$logger.trace("Activating dependency #{dep.name} first")
found_spec = embedded_gems_to_activate.find { |x| x.name == dep.name }
raise "Can't find #{dep.name}" unless found_spec
next if found_spec.activated
# found_spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
Gem::Specification.add_spec(found_spec) # Will add it to Gem::Specification.stubs too
raise "Failed to activate #{spec.name}" unless found_spec.activate
Bundler.rubygems.mark_loaded(found_spec)
stub = Gem::Specification.stubs_for(found_spec.name).first
bundler_stub = Bundler::StubSpecification.from_stub(stub)
if !locked_specs[dep].nil?
x = locked_specs[dep].first
x.instance_variable_set(:@version, found_spec.version)
class <<x
private
def use_exact_resolved_specifications?
@use_exact_resolved_specifications = false
end
end
# locked_specs.delete_by_name(dep.name)
# locked_specs[dep] = bundler_stub
extra_load_paths += found_spec.full_require_paths
end
end
Gem::Specification.add_spec(spec)
raise "Failed to activate #{spec.name}" unless spec.activate
Bundler.rubygems.mark_loaded(spec)
stub = Gem::Specification.stubs_for(spec.name).first
bundler_stub = Bundler::StubSpecification.from_stub(stub)
raise "That shouldn't happen" if locked_specs[spec.name].nil?
# locked_specs.delete_by_name(spec.name)
# locked_specs[spec.name] = bundler_stub
extra_load_paths += spec.full_require_paths
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Pfff. Seriously. That needs cleaning up I guess, I'm not really using the stubs: I thought I could swap the Bundler::LazySpecification with the Bundler::StubSpecification instead, but that doesn't work.

Anyways, the idea is to try to activate the dependencies of the spec before the spec is activated...

And I'm storing the load paths that are added

Comment on lines +1047 to +1050
# This is going to remove some stuff from the LOAD_PATH that we already loaded, when we really don't want to, so we readd them...
Bundler.setup(*keep_groups)
Bundler.rubygems.add_to_load_path(extra_load_paths - $LOAD_PATH)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is bad, but I guess you get the idea.

Copy link
Collaborator Author

@jmarrec jmarrec left a comment

Choose a reason for hiding this comment

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

Review for #5190

Comment on lines +665 to +668
# No env variable isn't the same as empty. Gem::PathSupport does stuff like @home = env["GEM_HOME"] || Gem.default_dir
ENV['GEM_HOME'] = ''
ENV['GEM_PATH'] = ''
ENV['GEM_SPEC_CACHE'] = ''
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

#5190 Do not leave GEM_HOME etc to be undefined, it's not the same as having a blank. + Call Gem::clear_paths

https://github.com/ruby/ruby/tree/v3_2_2lib/rubygems/path_support.rb#L8

# puts $LOAD_PATH

# TODO: double check and update platform-specific includes
$LOAD_PATH.clear
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Clear the LOAD_PATH early on, so we don't pick up filesystem stuff.

Comment on lines 709 to 756
# Instead of loading the generated (at build time) rbconfig.rb then manually
# fixing the CONFIG values, we load the original file, then we do replacements
# and we let the "magic" RbConfig::expand happen which has less chances of
# screw ups
def require_rb_config_with_patch
path_with_extension = EmbeddedScripting.fileNames.find{|x| x.include?('rbconfig.rb')}
if $LOADED.include?(path_with_extension)
return false
end

original_directory = Dir.pwd
$LOADED << path_with_extension
s = EmbeddedScripting::getFileAsString(path_with_extension)
s = OpenStudio::preprocess_ruby_script(s)

s = s.gsub(/CONFIG\["prefix"\] = .*/, 'CONFIG["prefix"] = ":"').gsub(/CONFIG\["libdir"\] = .*/, 'CONFIG["libdir"] = "$(prefix)"')

result = Kernel::eval(s, BINDING, path_with_extension)

current_directory = Dir.pwd
if original_directory != current_directory
Dir.chdir(original_directory)
end

return result
end

require_rb_config_with_patch

module RbConfig
def RbConfig.ruby
EmbeddedScripting::applicationFilePath;
end
end

# This is going to be used by rubygems/defaults.rb#default_dir
# RbConfig::CONFIG["rubylibprefix"] = ':/ruby'
# Instead of fixing just this one, we globally fix the prefix
# if RbConfig::CONFIG['prefix'] == '/'
# # Normally CONFIG["libdir"] = "$(prefix)/lib" but we want just $(prefix)
# puts "Fixing RbConfig prefix from #{RbConfig::CONFIG['prefix']} to ':'"
# libdir = RbConfig::CONFIG['libdir']
# RbConfig::CONFIG.transform_values!{ |val| val.gsub(libdir, ':').gsub('//', ':/') }
# RbConfig::CONFIG['bindir'] = File.dirname(EmbeddedScripting::applicationFilePath)
# end
raise "rubylibprefix isn't correct, it's '#{RbConfig::CONFIG["rubylibprefix"]}' but should be ':/ruby' "unless RbConfig::CONFIG["rubylibprefix"] == ':/ruby'

# NOTE: fileutils requires rbconfig, so we have to do our RbConfig shenanigans beforehand
Copy link
Collaborator Author

@jmarrec jmarrec Apr 8, 2025

Choose a reason for hiding this comment

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

Pfff.

I really only needed to fix rubylibprefix

https://github.com/ruby/ruby/blob/e51014f9c05aa65cbf203442d37fef7c12390015/lib/rubygems/defaults.rb#L36-L38

https://github.com/ruby/ruby/blob/v3_2_2/lib/rubygems/defaults.rb#L36-L38

or to path Gem.default_dir. But having the wrong prefix through RbConfig::CONFIG is recipe for disaster. So I chose to patch it fully.

class Gem
  def self.default_dir
    @default_dir ||= File.join(RbConfig::CONFIG["rubylibprefix"], "gems", RbConfig::CONFIG["ruby_version"])
  end
end

RbCONFIG is weird as hell but it'll expand some $(var_name) when it's first loaded, so I'm going to be using that to minimize the chances of screwing up. cf commit message on 03009e0 to see the rbconfig.rb that I have via conan ruby.

Comment on lines +756 to +769
# module Gem
# def self.default_dir
# @default_dir = ""
# end
#
# def self.find_home
# ""
# end
#
# def self.default_specifications_dir
# @default_specifications_dir = ""
# end
# end
#
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I didn't need this after fixing the RbConfig stuff, but we might...

# end
# end
#
Gem.clear_paths
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is going to force recomputing Gem @paths

Could have done Gem.paths = {'GEM_HOME' => xxx, 'GEM_PATH' => xxx, 'GEM_SPEC_CACHE' => xx}, but this is much better.

RubyEngine::setEmbeddedGems does:

  • setupEmbeddedGemsClearEnvVars: set all three vars in ENV to ''
  • initEmbeddedGems: will load rubygems
  • setGemPathDir, setRubyEnvVarPath(various including GEM_HOME): all of these tweak ENV only if the path ins't empty, so it'll stay a '' blank string if not supplied
  • locateEmbeddedGems calls Gem.clear_paths here. So paths is recomputed using the ENV variables via path_support, and will pick up the variables that were added (or not) to do so

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

https://github.com/ruby/ruby/blob/e51014f9c05aa65cbf203442d37fef7c12390015/lib/rubygems.rb#L313-L323

  ##
  # Reset the +dir+ and +path+ values.  The next time +dir+ or +path+
  # is requested, the values will be calculated from scratch.  This is
  # mainly used by the unit tests to provide test isolation.


  def self.clear_paths
    @paths         = nil
    @user_home     = nil
    Gem::Specification.reset
    Gem::Security.reset if defined?(Gem::Security)
  end

https://github.com/ruby/ruby/blob/e51014f9c05aa65cbf203442d37fef7c12390015/lib/rubygems.rb#L358-L363

  # Retrieve the PathSupport object that RubyGems uses to
  # lookup files.


  def self.paths
    @paths ||= Gem::PathSupport.new(ENV)
  end

@jmarrec
Copy link
Collaborator Author

jmarrec commented Apr 8, 2025

bundle_native_embedded is failing.

cd OpenStudio/src/cli/test/bundle_native_embedded
# bundle install as usual

$os_build/Products/openstudio --bundle Gemfile --bundle_path ./test_gems --loglevel Trace test.rb

[ruby] <-2> Activating Bundler gem :/ruby/gems/3.2.0/specifications/bundler-2.4.10.gemspec
[ruby] <-3> Requiring bundler
[ruby] <-1> without_groups = test
[ruby] <-1> g = default
[ruby] <-1> Bundling with groups [default]
[ruby] <-3> embedded_gems_to_activate.each: spec: json
[ruby] <-2> Removing native gem json from Bundler locked_specs (version 2.10.2), using the embedded dependency (CLI one has version 2.6.3)
[ruby] <-3> Gems having json as a dependency: {"rubocop"=>"~> 2.3"}
[ruby] <-3> embedded_gems_to_activate.each: spec: racc
[ruby] <-2> Removing native gem racc from Bundler locked_specs (version 1.8.1), using the embedded dependency (CLI one has version 1.6.2)
[ruby] <-3> Gems having racc as a dependency: {"parser"=>">= 0"}
Found no changes, using resolution from the lockfile
Source locally installed gems is ignoring #<Bundler::StubSpecification name=prism version=1.4.0 platform=ruby> because it is missing extensions
Failed to execute '/home/julien/Software/Others/OpenStudio/src/cli/test/bundle_native_embedded/test.rb

Pfffff. rubcop-ast added prism as a dependency 2 weeks ago: rubocop/rubocop-ast@32338bf

@jmarrec
Copy link
Collaborator Author

jmarrec commented Apr 8, 2025

@anchapin please fixup the ubuntu CI, they seem offline

image

I'm going to try to cancel the runs..

space too low:

https://ci.openstudio.net/computer/nrel%5Fdocker%5Fvcpu4%5F2/

I kicked vcpu4_2 back online anyways.

vcpu4_1 cannot be kicked back up.

SSHLauncher{host='10.20.5.83', port=22, credentialsId='jenkins-worker-node-key', jvmOptions='', javaPath='', prefixStartSlaveCmd='', suffixStartSlaveCmd='', launchTimeoutSeconds=60, maxNumRetries=10, retryWaitTime=15, sshHostKeyVerificationStrategy=hudson.plugins.sshslaves.verifiers.ManuallyTrustedKeyVerificationStrategy, tcpNoDelay=true, trackCredentials=true}
[04/08/25 13:44:17] [SSH] Opening SSH connection to xx.xxx.xxx.xxx.
[04/08/25 13:44:17] [SSH] SSH host key matches key seen previously for this host. Connection will be allowed.

ERROR: Server rejected the 1 private key(s) for jenkins (credentialId:jenkins-worker-node-key/method:publickey)
[04/08/25 13:44:17] [SSH] Authentication failed.
Authentication failed.
[04/08/25 13:44:17] Launch failed - cleaning up connection
[04/08/25 13:44:17] [SSH] Connection closed.

@jmarrec jmarrec changed the title Fix #5388 - --bundle options not working for CLI in docker-openstudio, possibly OS itself Fix #5388 - --bundle options not working for CLI in docker-openstudio, possibly OS itself + Fix #5190 - Don't pick up system gem in CLI Apr 8, 2025
@anchapin
Copy link
Collaborator

anchapin commented Apr 9, 2025

@jmarrec I freed up space on one of the boxes. I will keep checking for other issue.

@shorowit
Copy link
Contributor

shorowit commented Apr 9, 2025

I confirmed that the system gems no longer show up under gem_list.

@kbenne
Copy link
Contributor

kbenne commented Apr 30, 2025

This whole thing makes me shudder and I'm sure it doesn't please you either @jmarrec. I don't really know what to say, except time will tell if there are any unwanted side effects.

@kbenne kbenne merged commit 3e0e2c2 into develop Apr 30, 2025
3 of 6 checks passed
@jmarrec jmarrec deleted the 5388-Bundle branch May 5, 2025 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component - CLI Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--bundle options not working for CLI in docker-openstudio, possibly OS itself CLI includes system paths in the gem search path

7 participants