Make the gem build on TruffleRuby (#27660)

* replace darwin checks in extconf.rb to exclude TruffleRuby

* inherit RANLIB and STRIP from RbConfig, set LDXX

* enable overriding ranlib command in top-level makefile

* ensure the -no_warning_for_no_symbols flag is only used with Apple's ranlib

* don't embed openssl & zlib on truffleruby

* add RbConfig's cppflag to CPPFLAGS when using TruffleRuby

* this ensure the paths to find the system's OpenSSL are set up correctly with TruffleRuby (includes being able to find an OpenSSL installed via Homebrew etc)

* don't statically link standard libraries on Linux with Truffleruby

* This does not work when compiling to bitcode.

* Prefer SIGTERM to SIGQUIT for graceful shutdown in examples

* Overriding SIGQUIT is suboptimal, for example on JVM where it is very
  useful to dump the thread stacktraces.

* Keep the rb_tr_abi_version symbol for TruffleRuby in grpc_c.so

* Otherwise TruffleRuby cannot verify the ABI version is correct.
* See https://github.com/oracle/truffleruby/issues/2386

* Use RbConfig::CONFIG['STRIP'] instead of just `strip`

* Use a local variable for apple_toolchain for consistency

* Add a comment about -static-libgcc -static-libstdc++ and TruffleRuby

* Split comment into two for openssl/zlib

Co-authored-by: Nicolas Laurent <nicolas.laurent@oracle.com>
pull/30132/head
Benoit Daloze 2 years ago committed by GitHub
parent eb5ae61470
commit 0a5d9828c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      Makefile
  2. 4
      examples/ruby/greeter_server.rb
  3. 4
      examples/ruby/route_guide/route_guide_server.rb
  4. 2
      src/ruby/ext/grpc/ext-export-truffleruby.clang
  5. 7
      src/ruby/ext/grpc/ext-export-truffleruby.gcc
  6. 65
      src/ruby/ext/grpc/extconf.rb
  7. 9
      templates/Makefile.template

27
Makefile generated

@ -298,6 +298,13 @@ endif
INSTALL ?= install INSTALL ?= install
RM ?= rm -f RM ?= rm -f
PKG_CONFIG ?= pkg-config PKG_CONFIG ?= pkg-config
RANLIB ?= ranlib
ifeq ($(SYSTEM),Darwin)
APPLE_RANLIB = $(shell [[ "`$(RANLIB) -V 2>/dev/null`" == "Apple Inc."* ]]; echo $$?)
ifeq ($(APPLE_RANLIB),0)
RANLIBFLAGS = -no_warning_for_no_symbols
endif
endif
ifndef VALID_CONFIG_$(CONFIG) ifndef VALID_CONFIG_$(CONFIG)
$(error Invalid CONFIG value '$(CONFIG)') $(error Invalid CONFIG value '$(CONFIG)')
@ -857,7 +864,7 @@ $(LIBDIR)/$(CONFIG)/libaddress_sorting.a: $(LIBADDRESS_SORTING_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libaddress_sorting.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBADDRESS_SORTING_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBADDRESS_SORTING_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libaddress_sorting.a
endif endif
@ -984,7 +991,7 @@ $(LIBDIR)/$(CONFIG)/libgpr.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgpr.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgpr.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBGPR_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBGPR_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgpr.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libgpr.a
endif endif
@ -1746,7 +1753,7 @@ $(LIBDIR)/$(CONFIG)/libgrpc.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBGRPC_OBJS) $(LIBGPR_OBJS) $(LIBGRPC_ABSEIL_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(RE2_MERGE_OBJS) $(UPB_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBGRPC_OBJS) $(LIBGPR_OBJS) $(LIBGRPC_ABSEIL_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(RE2_MERGE_OBJS) $(UPB_MERGE_OBJS) $(OPENSSL_MERGE_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc.a
endif endif
@ -2144,7 +2151,7 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTI
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBGRPC_UNSECURE_OBJS) $(LIBGPR_OBJS) $(LIBGRPC_ABSEIL_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(RE2_MERGE_OBJS) $(UPB_MERGE_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBGRPC_UNSECURE_OBJS) $(LIBGPR_OBJS) $(LIBGRPC_ABSEIL_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(RE2_MERGE_OBJS) $(UPB_MERGE_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a
endif endif
@ -2456,7 +2463,7 @@ $(LIBDIR)/$(CONFIG)/libboringssl.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_D
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl.a $(LIBBORINGSSL_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl.a $(LIBBORINGSSL_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl.a
endif endif
@ -2504,7 +2511,7 @@ $(LIBDIR)/$(CONFIG)/libre2.a: $(LIBRE2_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libre2.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libre2.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libre2.a $(LIBRE2_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libre2.a $(LIBRE2_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libre2.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libre2.a
endif endif
@ -2544,7 +2551,7 @@ $(LIBDIR)/$(CONFIG)/libupb.a: $(LIBUPB_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libupb.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libupb.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libupb.a $(LIBUPB_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libupb.a $(LIBUPB_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libupb.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libupb.a
endif endif
@ -2603,7 +2610,7 @@ $(LIBDIR)/$(CONFIG)/libz.a: $(LIBZ_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libz.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libz.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libz.a $(LIBZ_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libz.a $(LIBZ_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libz.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libz.a
endif endif
@ -2686,7 +2693,7 @@ $(LIBDIR)/$(CONFIG)/libares.a: $(LIBARES_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libares.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libares.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libares.a $(LIBARES_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libares.a $(LIBARES_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libares.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libares.a
endif endif
@ -2810,7 +2817,7 @@ $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a: $(LIBGRPC_ABSEIL_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
$(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a $(LIBGRPC_ABSEIL_OBJS) $(Q) $(AR) $(ARFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a $(LIBGRPC_ABSEIL_OBJS)
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/libgrpc_abseil.a
endif endif

@ -39,10 +39,10 @@ def main
s = GRPC::RpcServer.new s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
s.handle(GreeterServer) s.handle(GreeterServer)
# Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to # Runs the server with SIGHUP, SIGINT and SIGTERM signal handlers to
# gracefully shutdown. # gracefully shutdown.
# User could also choose to run server via call to run_till_terminated # User could also choose to run server via call to run_till_terminated
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) s.run_till_terminated_or_interrupted([1, 'int', 'SIGTERM'])
end end
main main

@ -172,10 +172,10 @@ def main
s.add_http2_port(port, :this_port_is_insecure) s.add_http2_port(port, :this_port_is_insecure)
GRPC.logger.info("... running insecurely on #{port}") GRPC.logger.info("... running insecurely on #{port}")
s.handle(ServerImpl.new(feature_db)) s.handle(ServerImpl.new(feature_db))
# Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to # Runs the server with SIGHUP, SIGINT and SIGTERM signal handlers to
# gracefully shutdown. # gracefully shutdown.
# User could also choose to run server via call to run_till_terminated # User could also choose to run server via call to run_till_terminated
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) s.run_till_terminated_or_interrupted([1, 'int', 'SIGTERM'])
end end
main main

@ -0,0 +1,2 @@
_Init_grpc_c
_rb_tr_abi_version

@ -0,0 +1,7 @@
grpc_1.0 {
global:
Init_grpc_c;
rb_tr_abi_version;
local:
*;
};

@ -20,6 +20,8 @@ bsd = RUBY_PLATFORM =~ /bsd/
darwin = RUBY_PLATFORM =~ /darwin/ darwin = RUBY_PLATFORM =~ /darwin/
linux = RUBY_PLATFORM =~ /linux/ linux = RUBY_PLATFORM =~ /linux/
cross_compiling = ENV['RCD_HOST_RUBY_VERSION'] # set by rake-compiler-dock in build containers cross_compiling = ENV['RCD_HOST_RUBY_VERSION'] # set by rake-compiler-dock in build containers
# TruffleRuby uses the Sulong LLVM runtime, which is different from Apple's.
apple_toolchain = darwin && RUBY_ENGINE != 'truffleruby'
grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..')) grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
@ -27,30 +29,53 @@ grpc_config = ENV['GRPC_CONFIG'] || 'opt'
ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.10' ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.10'
if ENV['AR'].nil? || ENV['AR'].size == 0 def env_unset?(name)
ENV['AR'] = RbConfig::CONFIG['AR'] ENV[name].nil? || ENV[name].size == 0
end end
if ENV['CC'].nil? || ENV['CC'].size == 0
ENV['CC'] = RbConfig::CONFIG['CC'] def rbconfig_set?(name)
RbConfig::CONFIG[name] && RbConfig::CONFIG[name].size > 0
end end
if ENV['CXX'].nil? || ENV['CXX'].size == 0
ENV['CXX'] = RbConfig::CONFIG['CXX'] def inherit_rbconfig(name)
ENV[name] = RbConfig::CONFIG[name] if env_unset?(name) && rbconfig_set?(name)
end end
if ENV['LD'].nil? || ENV['LD'].size == 0
ENV['LD'] = ENV['CC'] def env_append(name, string)
ENV[name] ||= ''
ENV[name] += ' ' + string
end end
if darwin && !cross_compiling inherit_rbconfig 'AR'
inherit_rbconfig 'CC'
inherit_rbconfig 'CXX'
inherit_rbconfig 'RANLIB'
inherit_rbconfig 'STRIP'
inherit_rbconfig 'CPPFLAGS'
inherit_rbconfig 'LDFLAGS'
ENV['LD'] = ENV['CC'] if env_unset?('LD')
ENV['LDXX'] = ENV['CXX'] if env_unset?('LDXX')
if RUBY_ENGINE == 'truffleruby'
# ensure we can find the system's OpenSSL
env_append 'CPPFLAGS', RbConfig::CONFIG['cppflags']
end
if apple_toolchain && !cross_compiling
ENV['AR'] = 'libtool' ENV['AR'] = 'libtool'
ENV['ARFLAGS'] = '-o' ENV['ARFLAGS'] = '-o'
end end
ENV['EMBED_OPENSSL'] = 'true' # Don't embed on TruffleRuby (constant-time crypto is unsafe with Sulong, slow build times)
ENV['EMBED_ZLIB'] = 'true' ENV['EMBED_OPENSSL'] = (RUBY_ENGINE != 'truffleruby').to_s
# Don't embed on TruffleRuby (the system zlib is already linked for the zlib C extension, slow build times)
ENV['EMBED_ZLIB'] = (RUBY_ENGINE != 'truffleruby').to_s
ENV['EMBED_CARES'] = 'true' ENV['EMBED_CARES'] = 'true'
ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG'] ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
if darwin && !cross_compiling if apple_toolchain && !cross_compiling
if RUBY_PLATFORM =~ /arm64/ if RUBY_PLATFORM =~ /arm64/
ENV['ARCH_FLAGS'] = '-arch arm64' ENV['ARCH_FLAGS'] = '-arch arm64'
else else
@ -58,11 +83,11 @@ if darwin && !cross_compiling
end end
end end
ENV['CPPFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE' env_append 'CPPFLAGS', '-DGPR_BACKWARDS_COMPATIBILITY_MODE'
ENV['CPPFLAGS'] += ' -DGRPC_XDS_USER_AGENT_NAME_SUFFIX="\"RUBY\"" ' env_append 'CPPFLAGS', '-DGRPC_XDS_USER_AGENT_NAME_SUFFIX="\"RUBY\""'
require_relative '../../lib/grpc/version' require_relative '../../lib/grpc/version'
ENV['CPPFLAGS'] += ' -DGRPC_XDS_USER_AGENT_VERSION_SUFFIX="\"' + GRPC::VERSION + '\"" ' env_append 'CPPFLAGS', '-DGRPC_XDS_USER_AGENT_VERSION_SUFFIX="\"' + GRPC::VERSION + '\""'
output_dir = File.expand_path(RbConfig::CONFIG['topdir']) output_dir = File.expand_path(RbConfig::CONFIG['topdir'])
grpc_lib_dir = File.join(output_dir, 'libs', grpc_config) grpc_lib_dir = File.join(output_dir, 'libs', grpc_config)
@ -87,8 +112,9 @@ end
$CFLAGS << ' -I' + File.join(grpc_root, 'include') $CFLAGS << ' -I' + File.join(grpc_root, 'include')
ext_export_file = File.join(grpc_root, 'src', 'ruby', 'ext', 'grpc', 'ext-export') ext_export_file = File.join(grpc_root, 'src', 'ruby', 'ext', 'grpc', 'ext-export')
ext_export_file += '-truffleruby' if RUBY_ENGINE == 'truffleruby'
$LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if linux $LDFLAGS << ' -Wl,--version-script="' + ext_export_file + '.gcc"' if linux
$LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if darwin $LDFLAGS << ' -Wl,-exported_symbols_list,"' + ext_export_file + '.clang"' if apple_toolchain
$LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows $LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows
if grpc_config == 'gcov' if grpc_config == 'gcov'
@ -101,7 +127,10 @@ if grpc_config == 'dbg'
end end
$LDFLAGS << ' -Wl,-wrap,memcpy' if linux $LDFLAGS << ' -Wl,-wrap,memcpy' if linux
$LDFLAGS << ' -static-libgcc -static-libstdc++' if linux # Do not statically link standard libraries on TruffleRuby as this does not work when compiling to bitcode
if linux && RUBY_ENGINE != 'truffleruby'
$LDFLAGS << ' -static-libgcc -static-libstdc++'
end
$LDFLAGS << ' -static' if windows $LDFLAGS << ' -static' if windows
$CFLAGS << ' -std=c11 ' $CFLAGS << ' -std=c11 '
@ -114,7 +143,7 @@ puts 'Generating Makefile for ' + output
create_makefile(output) create_makefile(output)
strip_tool = RbConfig::CONFIG['STRIP'] strip_tool = RbConfig::CONFIG['STRIP']
strip_tool += ' -x' if darwin strip_tool += ' -x' if apple_toolchain
if grpc_config == 'opt' if grpc_config == 'opt'
File.open('Makefile.new', 'w') do |o| File.open('Makefile.new', 'w') do |o|

@ -185,6 +185,13 @@
INSTALL ?= install INSTALL ?= install
RM ?= rm -f RM ?= rm -f
PKG_CONFIG ?= pkg-config PKG_CONFIG ?= pkg-config
RANLIB ?= ranlib
ifeq ($(SYSTEM),Darwin)
APPLE_RANLIB = $(shell [[ "`$(RANLIB) -V 2>/dev/null`" == "Apple Inc."* ]]; echo $$?)
ifeq ($(APPLE_RANLIB),0)
RANLIBFLAGS = -no_warning_for_no_symbols
endif
endif
ifndef VALID_CONFIG_$(CONFIG) ifndef VALID_CONFIG_$(CONFIG)
$(error Invalid CONFIG value '$(CONFIG)') $(error Invalid CONFIG value '$(CONFIG)')
@ -941,7 +948,7 @@
% endif % endif
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(Q) $(RANLIB) $(RANLIBFLAGS) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
endif endif
<% <%

Loading…
Cancel
Save